!--------------------------------------------------------------------------------------------------!
!   CP2K: A general program to perform molecular dynamics simulations                              !
!   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
!                                                                                                  !
!   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
!--------------------------------------------------------------------------------------------------!

! **************************************************************************************************
!> \par History
!>      Teodoro Laino [Teo] 11.2005 : Reorganizing the structures to optimize
!>                                    memory management
!> \author CJM
! **************************************************************************************************
MODULE pair_potential_types

   USE kinds,                           ONLY: default_path_length,&
                                              default_string_length,&
                                              dp
   USE memory_utilities,                ONLY: reallocate
   USE splines_types,                   ONLY: spline_data_p_copy,&
                                              spline_data_p_release,&
                                              spline_data_p_type,&
                                              spline_factor_copy,&
                                              spline_factor_release,&
                                              spline_factor_type
#include "./base/base_uses.f90"

   IMPLICIT NONE

   CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pair_potential_types'

   PRIVATE
   ! when adding a new nonbonded potential please update also the list_pot
   ! used for the linear scaling screening of potential calculation
   INTEGER, PUBLIC, PARAMETER :: multi_type = -1, &
                                 nn_type = 0, &
                                 lj_type = 1, &
                                 lj_charmm_type = 2, &
                                 ft_type = 3, &
                                 wl_type = 4, &
                                 gw_type = 5, &
                                 ip_type = 6, &
                                 ea_type = 7, &
                                 b4_type = 8, &
                                 bm_type = 9, &
                                 gp_type = 10, &
                                 tersoff_type = 11, &
                                 ftd_type = 12, &
                                 siepmann_type = 13, &
                                 gal_type = 14, &
                                 quip_type = 15, &
                                 nequip_type = 16, &
                                 allegro_type = 17, &
                                 gal21_type = 18, &
                                 tab_type = 19, &
                                 deepmd_type = 20

   INTEGER, PUBLIC, PARAMETER, DIMENSION(21) :: list_pot = (/nn_type, &
                                                             lj_type, &
                                                             lj_charmm_type, &
                                                             ft_type, &
                                                             wl_type, &
                                                             gw_type, &
                                                             ip_type, &
                                                             ea_type, &
                                                             b4_type, &
                                                             bm_type, &
                                                             gp_type, &
                                                             tersoff_type, &
                                                             ftd_type, &
                                                             siepmann_type, &
                                                             gal_type, &
                                                             quip_type, &
                                                             nequip_type, &
                                                             allegro_type, &
                                                             gal21_type, &
                                                             tab_type, &
                                                             deepmd_type/)

   ! Shell model
   INTEGER, PUBLIC, PARAMETER :: nosh_nosh = 0, &
                                 nosh_sh = 1, &
                                 sh_sh = 2

   INTEGER, PUBLIC, PARAMETER, DIMENSION(3) :: list_sh_type = (/nosh_nosh, nosh_sh, sh_sh/)

   ! Single Spline generation info
   REAL(KIND=dp), PARAMETER, PUBLIC         :: not_initialized = -HUGE(0.0_dp)
   INTEGER, PARAMETER, DIMENSION(2), PUBLIC :: do_potential_single_allocation = (/lj_type, lj_charmm_type/)
   INTEGER, PARAMETER, DIMENSION(2), PUBLIC :: no_potential_single_allocation = (/-HUGE(0), -HUGE(0)/)
   INTEGER, DIMENSION(2), PUBLIC            :: potential_single_allocation

   PUBLIC :: pair_potential_reallocate

   PUBLIC :: pair_potential_single_copy, &
             pair_potential_single_add, &
             pair_potential_single_clean, &
             pair_potential_single_type

   PUBLIC :: pair_potential_pp_create, &
             pair_potential_pp_release, &
             pair_potential_pp_type

   PUBLIC :: pair_potential_p_type, &
             pair_potential_p_release

   PUBLIC :: ft_pot_type, &
             ipbv_pot_type, &
             eam_pot_type, &
             quip_pot_type, &
             nequip_pot_type, &
             allegro_pot_type, &
             deepmd_pot_type, &
             tersoff_pot_type, &
             siepmann_pot_type, &
             gal_pot_type, &
             gal21_pot_type, &
             tab_pot_type

   PUBLIC :: pair_potential_lj_create
   PUBLIC :: compare_pot

! **************************************************************************************************
   TYPE ipbv_pot_type
      REAL(KIND=dp), DIMENSION(2:15) :: a = 0.0_dp
      REAL(KIND=dp) :: rcore = 0.0_dp
      REAL(KIND=dp) :: m = 0.0_dp
      REAL(KIND=dp) :: b = 0.0_dp
   END TYPE ipbv_pot_type

! **************************************************************************************************
   TYPE lj_pot_type
      REAL(KIND=dp) :: epsilon = 0.0_dp
      REAL(KIND=dp) :: sigma6 = 0.0_dp
      REAL(KIND=dp) :: sigma12 = 0.0_dp
   END TYPE Lj_pot_type

! **************************************************************************************************
   TYPE ft_pot_type
      REAL(KIND=dp) :: A = 0.0_dp
      REAL(KIND=dp) :: B = 0.0_dp
      REAL(KIND=dp) :: C = 0.0_dp
      REAL(KIND=dp) :: D = 0.0_dp
   END TYPE ft_pot_type

! **************************************************************************************************
   TYPE ftd_pot_type
      REAL(KIND=dp) :: A = 0.0_dp
      REAL(KIND=dp) :: B = 0.0_dp
      REAL(KIND=dp) :: C = 0.0_dp
      REAL(KIND=dp) :: D = 0.0_dp
      REAL(KIND=dp), DIMENSION(2) :: BD = 0.0_dp
   END TYPE ftd_pot_type

! **************************************************************************************************
   TYPE williams_pot_type
      REAL(KIND=dp) :: a = 0.0_dp
      REAL(KIND=dp) :: b = 0.0_dp
      REAL(KIND=dp) :: c = 0.0_dp
   END TYPE williams_pot_type

! **************************************************************************************************
   TYPE goodwin_pot_type
      REAL(KIND=dp) :: vr0 = 0.0_dp
      REAL(KIND=dp) :: m = 0.0_dp, mc = 0.0_dp
      REAL(KIND=dp) :: d = 0.0_dp, dc = 0.0_dp
   END TYPE goodwin_pot_type

! **************************************************************************************************
   TYPE eam_pot_type
      CHARACTER(LEN=default_path_length)     :: eam_file_name = ""
      INTEGER                                 :: npoints = 0
      REAL(KIND=dp)                          :: drar = 0.0_dp, drhoar = 0.0_dp, acutal = 0.0_dp
      REAL(KIND=dp), POINTER, DIMENSION(:)    :: rho => NULL(), phi => NULL(), frho => NULL(), rhoval => NULL(), rval => NULL()
      REAL(KIND=dp), POINTER, DIMENSION(:)    :: rhop => NULL(), phip => NULL(), frhop => NULL()
   END TYPE eam_pot_type

! **************************************************************************************************
   TYPE deepmd_pot_type
      CHARACTER(LEN=default_path_length)     :: deepmd_file_name = 'NULL'
      INTEGER                                :: atom_deepmd_type = 0
   END TYPE deepmd_pot_type

! **************************************************************************************************
   TYPE quip_pot_type
      CHARACTER(LEN=default_path_length)     :: quip_file_name = ""
      CHARACTER(LEN=1024)                    :: init_args = ""
      CHARACTER(LEN=1024)                    :: calc_args = ""
   END TYPE quip_pot_type

! **************************************************************************************************
   TYPE nequip_pot_type
      CHARACTER(LEN=default_path_length)     :: nequip_file_name = 'NULL', nequip_version = 'NULL', &
                                                unit_coords = 'NULL', unit_forces = 'NULL', &
                                                unit_energy = 'NULL', unit_cell = 'NULL'
      CHARACTER(LEN=100), DIMENSION(:), ALLOCATABLE      :: type_names_torch
      REAL(KIND=dp)                          :: rcutsq = 0.0_dp, unit_coords_val = 1.0_dp, &
                                                unit_forces_val = 1.0_dp, unit_energy_val = 1.0_dp, &
                                                unit_cell_val = 1.0_dp
      LOGICAL                                :: do_nequip_sp = .FALSE.
   END TYPE nequip_pot_type

! **************************************************************************************************
   TYPE allegro_pot_type
      CHARACTER(LEN=default_path_length)     :: allegro_file_name = 'NULL', unit_cell = 'NULL', &
                                                nequip_version = 'NULL', unit_coords = 'NULL', &
                                                unit_forces = 'NULL', unit_energy = 'NULL'

      CHARACTER(LEN=100), DIMENSION(:), ALLOCATABLE      :: type_names_torch

      REAL(KIND=dp)                          :: rcutsq = 0.0_dp, unit_coords_val = 1.0_dp, &
                                                unit_forces_val = 1.0_dp, unit_cell_val = 1.0_dp, &
                                                unit_energy_val = 1.0_dp
      LOGICAL                                :: do_allegro_sp = .FALSE.
   END TYPE allegro_pot_type

! **************************************************************************************************
   TYPE buck4ran_pot_type
      REAL(KIND=dp) :: a = 0.0_dp
      REAL(KIND=dp) :: b = 0.0_dp
      REAL(KIND=dp) :: c = 0.0_dp
      REAL(KIND=dp) :: r1 = 0.0_dp
      REAL(KIND=dp) :: r2 = 0.0_dp
      REAL(KIND=dp) :: r3 = 0.0_dp
      INTEGER :: npoly1 = 0, npoly2 = 0
      REAL(KIND=dp), DIMENSION(0:10) :: poly1 = 0.0_dp
      REAL(KIND=dp), DIMENSION(0:10) :: poly2 = 0.0_dp
   END TYPE buck4ran_pot_type

! **************************************************************************************************
   TYPE buckmorse_pot_type
      REAL(KIND=dp) :: f0 = 0.0_dp
      REAL(KIND=dp) :: a1 = 0.0_dp
      REAL(KIND=dp) :: a2 = 0.0_dp
      REAL(KIND=dp) :: b1 = 0.0_dp
      REAL(KIND=dp) :: b2 = 0.0_dp
      REAL(KIND=dp) :: c = 0.0_dp
      REAL(KIND=dp) :: d = 0.0_dp
      REAL(KIND=dp) :: r0 = 0.0_dp
      REAL(KIND=dp) :: beta = 0.0_dp
   END TYPE buckmorse_pot_type

! **************************************************************************************************
   TYPE gp_pot_type
      INTEGER                                   :: myid = 0
      CHARACTER(LEN=default_path_length)       :: potential = ""
      CHARACTER(LEN=default_string_length), &
         POINTER, DIMENSION(:)                   :: parameters => NULL(), units => NULL()
      CHARACTER(LEN=default_string_length)     :: variables = ""
      REAL(KIND=dp), DIMENSION(:), POINTER      :: values => NULL()
   END TYPE gp_pot_type

! **************************************************************************************************
   TYPE tersoff_pot_type
      ! Get this stuff from the PRB V38, N14 9902 (1988) by Tersoff
      REAL(KIND=dp) :: A = 0.0_dp
      REAL(KIND=dp) :: B = 0.0_dp
      REAL(KIND=dp) :: lambda1 = 0.0_dp
      REAL(KIND=dp) :: lambda2 = 0.0_dp
      REAL(KIND=dp) :: alpha = 0.0_dp
      REAL(KIND=dp) :: beta = 0.0_dp
      REAL(KIND=dp) :: n = 0.0_dp
      REAL(KIND=dp) :: c = 0.0_dp
      REAL(KIND=dp) :: d = 0.0_dp
      REAL(KIND=dp) :: h = 0.0_dp
      REAL(KIND=dp) :: lambda3 = 0.0_dp
      REAL(KIND=dp) :: bigR = 0.0_dp ! Used to be R = Rij + D
      REAL(KIND=dp) :: bigD = 0.0_dp ! Used to be D = Rij - D
      REAL(KIND=dp) :: rcutsq = 0.0_dp ! Always set to (bigR+bigD)^2
   END TYPE tersoff_pot_type

! **************************************************************************************************
   TYPE siepmann_pot_type
      REAL(KIND=dp) :: B = 0.0_dp
      REAL(KIND=dp) :: D = 0.0_dp
      REAL(KIND=dp) :: E = 0.0_dp
      REAL(KIND=dp) :: F = 0.0_dp
      REAL(KIND=dp) :: beta = 0.0_dp
      REAL(KIND=dp) :: rcutsq = 0.0_dp
      LOGICAL        :: allow_oh_formation = .FALSE.
      LOGICAL        :: allow_h3o_formation = .FALSE.
      LOGICAL        :: allow_o_formation = .FALSE.
   END TYPE siepmann_pot_type

! **************************************************************************************************
   TYPE gal_pot_type
      CHARACTER(LEN=2) :: met1 = ""
      CHARACTER(LEN=2) :: met2 = ""
      REAL(KIND=dp) :: epsilon = 0.0_dp
      REAL(KIND=dp) :: bxy = 0.0_dp
      REAL(KIND=dp) :: bz = 0.0_dp
      REAL(KIND=dp) :: r1 = 0.0_dp
      REAL(KIND=dp) :: r2 = 0.0_dp
      REAL(KIND=dp) :: a1 = 0.0_dp
      REAL(KIND=dp) :: a2 = 0.0_dp
      REAL(KIND=dp) :: a3 = 0.0_dp
      REAL(KIND=dp) :: a4 = 0.0_dp
      REAL(KIND=dp) :: a = 0.0_dp
      REAL(KIND=dp) :: b = 0.0_dp
      REAL(KIND=dp) :: c = 0.0_dp
      REAL(KIND=dp), POINTER, DIMENSION(:) :: gcn => NULL()
      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)    :: n_vectors
      REAL(KIND=dp)  :: rcutsq = 0.0_dp
      LOGICAL        :: express = .FALSE.
   END TYPE gal_pot_type

! **************************************************************************************************

   TYPE gal21_pot_type
      CHARACTER(LEN=2) :: met1 = ""
      CHARACTER(LEN=2) :: met2 = ""
      REAL(KIND=dp) :: epsilon1 = 0.0_dp
      REAL(KIND=dp) :: epsilon2 = 0.0_dp
      REAL(KIND=dp) :: epsilon3 = 0.0_dp
      REAL(KIND=dp) :: bxy1 = 0.0_dp
      REAL(KIND=dp) :: bxy2 = 0.0_dp
      REAL(KIND=dp) :: bz1 = 0.0_dp
      REAL(KIND=dp) :: bz2 = 0.0_dp
      REAL(KIND=dp) :: r1 = 0.0_dp
      REAL(KIND=dp) :: r2 = 0.0_dp
      REAL(KIND=dp) :: a11 = 0.0_dp
      REAL(KIND=dp) :: a12 = 0.0_dp
      REAL(KIND=dp) :: a13 = 0.0_dp
      REAL(KIND=dp) :: a21 = 0.0_dp
      REAL(KIND=dp) :: a22 = 0.0_dp
      REAL(KIND=dp) :: a23 = 0.0_dp
      REAL(KIND=dp) :: a31 = 0.0_dp
      REAL(KIND=dp) :: a32 = 0.0_dp
      REAL(KIND=dp) :: a33 = 0.0_dp
      REAL(KIND=dp) :: a41 = 0.0_dp
      REAL(KIND=dp) :: a42 = 0.0_dp
      REAL(KIND=dp) :: a43 = 0.0_dp
      REAL(KIND=dp) :: AO1 = 0.0_dp
      REAL(KIND=dp) :: AO2 = 0.0_dp
      REAL(KIND=dp) :: BO1 = 0.0_dp
      REAL(KIND=dp) :: BO2 = 0.0_dp
      REAL(KIND=dp) :: c = 0.0_dp
      REAL(KIND=dp) :: AH1 = 0.0_dp
      REAL(KIND=dp) :: AH2 = 0.0_dp
      REAL(KIND=dp) :: BH1 = 0.0_dp
      REAL(KIND=dp) :: BH2 = 0.0_dp
      REAL(KIND=dp), POINTER, DIMENSION(:) :: gcn => NULL()
      REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)    :: n_vectors
      REAL(KIND=dp)  :: rcutsq = 0.0_dp
      LOGICAL        :: express = .FALSE.
   END TYPE gal21_pot_type

! **************************************************************************************************

   TYPE tab_pot_type
      CHARACTER(LEN=default_path_length)      :: tabpot_file_name = ""
      INTEGER                                 :: npoints = 0, index = 0
      REAL(KIND=dp)                           :: dr = 0.0_dp, rcut = 0.0_dp
      REAL(KIND=dp), POINTER, DIMENSION(:)    :: r => NULL(), e => NULL(), f => NULL()
   END TYPE tab_pot_type

! **************************************************************************************************

   TYPE pot_set_type
      REAL(KIND=dp)                      :: rmin = 0.0_dp, rmax = 0.0_dp
      TYPE(ipbv_pot_type), POINTER :: ipbv => NULL()
      TYPE(gp_pot_type), POINTER :: gp => NULL()
      TYPE(lj_pot_type), POINTER :: lj => NULL()
      TYPE(ft_pot_type), POINTER :: ft => NULL()
      TYPE(williams_pot_type), POINTER :: willis => NULL()
      TYPE(goodwin_pot_type), POINTER :: goodwin => NULL()
      TYPE(eam_pot_type), POINTER :: eam => NULL()
      TYPE(quip_pot_type), POINTER :: quip => NULL()
      TYPE(nequip_pot_type), POINTER :: nequip => NULL()
      TYPE(allegro_pot_type), POINTER :: allegro => NULL()
      TYPE(deepmd_pot_type), POINTER :: deepmd => NULL()
      TYPE(buck4ran_pot_type), POINTER :: buck4r => NULL()
      TYPE(buckmorse_pot_type), POINTER :: buckmo => NULL()
      TYPE(tersoff_pot_type), POINTER :: tersoff => NULL()
      TYPE(siepmann_pot_type), POINTER :: siepmann => NULL()
      TYPE(gal_pot_type), POINTER :: gal => NULL()
      TYPE(gal21_pot_type), POINTER :: gal21 => NULL()
      TYPE(ftd_pot_type), POINTER :: ftd => NULL()
      TYPE(tab_pot_type), POINTER :: tab => NULL()
   END TYPE pot_set_type

! **************************************************************************************************
   TYPE pair_potential_single_type
      REAL(KIND=dp) :: rcutsq = 0.0_dp
      REAL(KIND=dp) :: e_fac = 0.0_dp
      REAL(KIND=dp) :: e_fcc = 0.0_dp
      REAL(KIND=dp) :: e_fcs = 0.0_dp
      REAL(KIND=dp) :: e_fsc = 0.0_dp
      REAL(KIND=dp) :: z1 = 0.0_dp
      REAL(KIND=dp) :: z2 = 0.0_dp
      REAL(KIND=dp), DIMENSION(0:5) :: zbl_poly = 0.0_dp
      REAL(KIND=dp), DIMENSION(2) :: zbl_rcut = 0.0_dp
      LOGICAL        :: undef = .FALSE., & ! non-bonding interaction not defined
                        no_mb = .FALSE., & ! no many-body potential
                        no_pp = .FALSE. ! no pair (=two-body) potential
      INTEGER        :: shell_type = 0
      CHARACTER(LEN=default_string_length)   :: at1 = ""
      CHARACTER(LEN=default_string_length)   :: at2 = ""
      INTEGER, POINTER, DIMENSION(:)              :: TYPE => NULL()
      TYPE(pot_set_type), POINTER, DIMENSION(:) :: set => NULL()
      TYPE(spline_data_p_type), POINTER, DIMENSION(:) :: pair_spline_data => NULL()
      TYPE(spline_factor_type), POINTER :: spl_f => NULL()
   END TYPE pair_potential_single_type

! **************************************************************************************************
   TYPE pair_potential_type
      TYPE(pair_potential_single_type), POINTER :: pot => NULL()
   END TYPE pair_potential_type

! **************************************************************************************************
   TYPE pair_potential_p_type
      TYPE(pair_potential_type), DIMENSION(:), POINTER :: pot => NULL()
   END TYPE pair_potential_p_type

! **************************************************************************************************
   TYPE pair_potential_pp_type
      TYPE(pair_potential_type), DIMENSION(:, :), POINTER :: pot => NULL()
   END TYPE pair_potential_pp_type

CONTAINS

! **************************************************************************************************
!> \brief compare two different potentials
!> \param pot1 ...
!> \param pot2 ...
!> \param compare ...
!> \author Teodoro Laino [teo] 05.2006
! **************************************************************************************************
   SUBROUTINE compare_pot(pot1, pot2, compare)
      TYPE(pair_potential_single_type), POINTER          :: pot1, pot2
      LOGICAL, INTENT(OUT)                               :: compare

      INTEGER                                            :: i
      LOGICAL                                            :: mycompare

      compare = .FALSE.
      ! Preliminary checks

      CPASSERT(ASSOCIATED(pot1%type))
      CPASSERT(ASSOCIATED(pot2%type))
      IF (SIZE(pot1%type) /= SIZE(pot2%type)) RETURN
      IF (ANY(pot1%type /= pot2%type)) RETURN

      ! Checking the real values of parameters
      CPASSERT(ASSOCIATED(pot1%set))
      CPASSERT(ASSOCIATED(pot2%set))
      DO i = 1, SIZE(pot1%type)
         mycompare = .FALSE.
         SELECT CASE (pot1%type(i))
         CASE (lj_type, lj_charmm_type)
            IF ((pot1%set(i)%lj%epsilon == pot2%set(i)%lj%epsilon) .AND. &
                (pot1%set(i)%lj%sigma6 == pot2%set(i)%lj%sigma6) .AND. &
                (pot1%set(i)%lj%sigma12 == pot2%set(i)%lj%sigma12)) mycompare = .TRUE.
         CASE (wl_type)
            IF ((pot1%set(i)%willis%a == pot2%set(i)%willis%a) .AND. &
                (pot1%set(i)%willis%b == pot2%set(i)%willis%b) .AND. &
                (pot1%set(i)%willis%c == pot2%set(i)%willis%c)) mycompare = .TRUE.
         CASE (gw_type)
            IF ((pot1%set(i)%goodwin%vr0 == pot2%set(i)%goodwin%vr0) .AND. &
                (pot1%set(i)%goodwin%m == pot2%set(i)%goodwin%m) .AND. &
                (pot1%set(i)%goodwin%mc == pot2%set(i)%goodwin%mc) .AND. &
                (pot1%set(i)%goodwin%d == pot2%set(i)%goodwin%d) .AND. &
                (pot1%set(i)%goodwin%dc == pot2%set(i)%goodwin%dc)) mycompare = .TRUE.
         CASE (ea_type)
            ! Compare only if EAM have the same number of points
            IF (pot1%set(i)%eam%npoints == pot2%set(i)%eam%npoints) THEN
               IF ((pot1%set(i)%eam%drar == pot2%set(i)%eam%drar) .AND. &
                   (pot1%set(i)%eam%drhoar == pot2%set(i)%eam%drhoar) .AND. &
                   (pot1%set(i)%eam%acutal == pot2%set(i)%eam%acutal) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%rho - pot2%set(i)%eam%rho)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%phi - pot2%set(i)%eam%phi)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%frho - pot2%set(i)%eam%frho)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%rhoval - pot2%set(i)%eam%rhoval)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%rval - pot2%set(i)%eam%rval)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%rhop - pot2%set(i)%eam%rhop)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%phip - pot2%set(i)%eam%phip)) == 0.0_dp) .AND. &
                   (SUM(ABS(pot1%set(i)%eam%frhop - pot2%set(i)%eam%frhop)) == 0.0_dp)) mycompare = .TRUE.
            END IF
         CASE (deepmd_type)
            IF ((pot1%set(i)%deepmd%deepmd_file_name == pot2%set(i)%deepmd%deepmd_file_name) .AND. &
                (pot1%set(i)%deepmd%atom_deepmd_type == pot2%set(i)%deepmd%atom_deepmd_type)) mycompare = .TRUE.
         CASE (quip_type)
            IF ((pot1%set(i)%quip%quip_file_name == pot2%set(i)%quip%quip_file_name) .AND. &
                (pot1%set(i)%quip%init_args == pot2%set(i)%quip%init_args) .AND. &
                (pot1%set(i)%quip%calc_args == pot2%set(i)%quip%calc_args)) mycompare = .TRUE.
         CASE (nequip_type)
            IF ((pot1%set(i)%nequip%nequip_file_name == pot2%set(i)%nequip%nequip_file_name) .AND. &
                (pot1%set(i)%nequip%unit_coords == pot2%set(i)%nequip%unit_coords) .AND. &
                (pot1%set(i)%nequip%unit_forces == pot2%set(i)%nequip%unit_forces) .AND. &
                (pot1%set(i)%nequip%unit_energy == pot2%set(i)%nequip%unit_energy) .AND. &
                (pot1%set(i)%nequip%unit_cell == pot2%set(i)%nequip%unit_cell)) mycompare = .TRUE.
         CASE (allegro_type)
            IF ((pot1%set(i)%allegro%allegro_file_name == pot2%set(i)%allegro%allegro_file_name) .AND. &
                (pot1%set(i)%allegro%unit_coords == pot2%set(i)%allegro%unit_coords) .AND. &
                (pot1%set(i)%allegro%unit_forces == pot2%set(i)%allegro%unit_forces) .AND. &
                (pot1%set(i)%allegro%unit_energy == pot2%set(i)%allegro%unit_energy) .AND. &
                (pot1%set(i)%allegro%unit_cell == pot2%set(i)%allegro%unit_cell)) mycompare = .TRUE.
         CASE (ft_type)
            IF ((pot1%set(i)%ft%A == pot2%set(i)%ft%A) .AND. &
                (pot1%set(i)%ft%B == pot2%set(i)%ft%B) .AND. &
                (pot1%set(i)%ft%C == pot2%set(i)%ft%C) .AND. &
                (pot1%set(i)%ft%D == pot2%set(i)%ft%D)) mycompare = .TRUE.
         CASE (ftd_type)
            IF ((pot1%set(i)%ftd%A == pot2%set(i)%ftd%A) .AND. &
                (pot1%set(i)%ftd%B == pot2%set(i)%ftd%B) .AND. &
                (pot1%set(i)%ftd%C == pot2%set(i)%ftd%C) .AND. &
                (pot1%set(i)%ftd%D == pot2%set(i)%ftd%D) .AND. &
                (ALL(pot1%set(i)%ftd%BD(:) == pot2%set(i)%ftd%BD(:)))) mycompare = .TRUE.
         CASE (ip_type)
            IF ((SUM(ABS(pot1%set(i)%ipbv%a - pot2%set(i)%ipbv%a)) == 0.0_dp) .AND. &
                (pot1%set(i)%ipbv%rcore == pot2%set(i)%ipbv%rcore) .AND. &
                (pot1%set(i)%ipbv%m == pot2%set(i)%ipbv%m) .AND. &
                (pot1%set(i)%ipbv%b == pot2%set(i)%ipbv%b)) mycompare = .TRUE.
         CASE (tersoff_type)
            IF ((pot1%set(i)%tersoff%A == pot2%set(i)%tersoff%A) .AND. &
                (pot1%set(i)%tersoff%B == pot2%set(i)%tersoff%B) .AND. &
                (pot1%set(i)%tersoff%lambda1 == pot2%set(i)%tersoff%lambda1) .AND. &
                (pot1%set(i)%tersoff%lambda2 == pot2%set(i)%tersoff%lambda2) .AND. &
                (pot1%set(i)%tersoff%alpha == pot2%set(i)%tersoff%alpha) .AND. &
                (pot1%set(i)%tersoff%beta == pot2%set(i)%tersoff%beta) .AND. &
                (pot1%set(i)%tersoff%n == pot2%set(i)%tersoff%n) .AND. &
                (pot1%set(i)%tersoff%c == pot2%set(i)%tersoff%c) .AND. &
                (pot1%set(i)%tersoff%d == pot2%set(i)%tersoff%d) .AND. &
                (pot1%set(i)%tersoff%h == pot2%set(i)%tersoff%h) .AND. &
                (pot1%set(i)%tersoff%lambda3 == pot2%set(i)%tersoff%lambda3) .AND. &
                (pot1%set(i)%tersoff%rcutsq == pot2%set(i)%tersoff%rcutsq) .AND. &
                (pot1%set(i)%tersoff%bigR == pot2%set(i)%tersoff%bigR) .AND. &
                (pot1%set(i)%tersoff%bigD == pot2%set(i)%tersoff%bigD)) mycompare = .TRUE.
         CASE (siepmann_type)
            IF ((pot1%set(i)%siepmann%B == pot2%set(i)%siepmann%B) .AND. &
                (pot1%set(i)%siepmann%D == pot2%set(i)%siepmann%D) .AND. &
                (pot1%set(i)%siepmann%E == pot2%set(i)%siepmann%E) .AND. &
                (pot1%set(i)%siepmann%F == pot2%set(i)%siepmann%F) .AND. &
                (pot1%set(i)%siepmann%beta == pot2%set(i)%siepmann%beta) .AND. &
                (pot1%set(i)%siepmann%rcutsq == pot2%set(i)%siepmann%rcutsq) .AND. &
                (pot1%set(i)%siepmann%allow_oh_formation .EQV. &
                 pot2%set(i)%siepmann%allow_oh_formation) .AND. &
                (pot1%set(i)%siepmann%allow_o_formation .EQV. &
                 pot2%set(i)%siepmann%allow_o_formation) .AND. &
                (pot1%set(i)%siepmann%allow_h3o_formation .EQV. &
                 pot2%set(i)%siepmann%allow_h3o_formation)) mycompare = .TRUE.
         CASE (gal_type)
            IF ((pot1%set(i)%gal%epsilon == pot2%set(i)%gal%epsilon) .AND. &
                (pot1%set(i)%gal%bxy == pot2%set(i)%gal%bxy) .AND. &
                (pot1%set(i)%gal%bz == pot2%set(i)%gal%bz) .AND. &
                (pot1%set(i)%gal%r1 == pot2%set(i)%gal%r1) .AND. &
                (pot1%set(i)%gal%r2 == pot2%set(i)%gal%r2) .AND. &
                (pot1%set(i)%gal%a1 == pot2%set(i)%gal%a1) .AND. &
                (pot1%set(i)%gal%a2 == pot2%set(i)%gal%a2) .AND. &
                (pot1%set(i)%gal%a3 == pot2%set(i)%gal%a3) .AND. &
                (pot1%set(i)%gal%a4 == pot2%set(i)%gal%a4) .AND. &
                (pot1%set(i)%gal%a == pot2%set(i)%gal%a) .AND. &
                (pot1%set(i)%gal%b == pot2%set(i)%gal%b) .AND. &
                (pot1%set(i)%gal%c == pot2%set(i)%gal%c) .AND. &
                (pot1%set(i)%gal%express .EQV. &
                 pot2%set(i)%gal%express) .AND. &
                (pot1%set(i)%gal%rcutsq == pot2%set(i)%gal%rcutsq)) mycompare = .TRUE.
         CASE (gal21_type)
            IF ((pot1%set(i)%gal21%epsilon1 == pot2%set(i)%gal21%epsilon1) .AND. &
                (pot1%set(i)%gal21%epsilon2 == pot2%set(i)%gal21%epsilon2) .AND. &
                (pot1%set(i)%gal21%epsilon3 == pot2%set(i)%gal21%epsilon3) .AND. &
                (pot1%set(i)%gal21%bxy1 == pot2%set(i)%gal21%bxy1) .AND. &
                (pot1%set(i)%gal21%bxy2 == pot2%set(i)%gal21%bxy1) .AND. &
                (pot1%set(i)%gal21%bz1 == pot2%set(i)%gal21%bz1) .AND. &
                (pot1%set(i)%gal21%bz2 == pot2%set(i)%gal21%bz2) .AND. &
                (pot1%set(i)%gal21%r1 == pot2%set(i)%gal21%r1) .AND. &
                (pot1%set(i)%gal21%r2 == pot2%set(i)%gal21%r2) .AND. &
                (pot1%set(i)%gal21%a11 == pot2%set(i)%gal21%a11) .AND. &
                (pot1%set(i)%gal21%a12 == pot2%set(i)%gal21%a12) .AND. &
                (pot1%set(i)%gal21%a13 == pot2%set(i)%gal21%a13) .AND. &
                (pot1%set(i)%gal21%a21 == pot2%set(i)%gal21%a21) .AND. &
                (pot1%set(i)%gal21%a22 == pot2%set(i)%gal21%a22) .AND. &
                (pot1%set(i)%gal21%a23 == pot2%set(i)%gal21%a23) .AND. &
                (pot1%set(i)%gal21%a31 == pot2%set(i)%gal21%a31) .AND. &
                (pot1%set(i)%gal21%a32 == pot2%set(i)%gal21%a32) .AND. &
                (pot1%set(i)%gal21%a33 == pot2%set(i)%gal21%a33) .AND. &
                (pot1%set(i)%gal21%a41 == pot2%set(i)%gal21%a41) .AND. &
                (pot1%set(i)%gal21%a42 == pot2%set(i)%gal21%a42) .AND. &
                (pot1%set(i)%gal21%a43 == pot2%set(i)%gal21%a43) .AND. &
                (pot1%set(i)%gal21%AO1 == pot2%set(i)%gal21%AO1) .AND. &
                (pot1%set(i)%gal21%AO2 == pot2%set(i)%gal21%AO2) .AND. &
                (pot1%set(i)%gal21%BO1 == pot2%set(i)%gal21%BO1) .AND. &
                (pot1%set(i)%gal21%BO2 == pot2%set(i)%gal21%BO2) .AND. &
                (pot1%set(i)%gal21%c == pot2%set(i)%gal21%c) .AND. &
                (pot1%set(i)%gal21%AH1 == pot2%set(i)%gal21%AH1) .AND. &
                (pot1%set(i)%gal21%AH2 == pot2%set(i)%gal21%AH2) .AND. &
                (pot1%set(i)%gal21%BH1 == pot2%set(i)%gal21%BH1) .AND. &
                (pot1%set(i)%gal21%BH2 == pot2%set(i)%gal21%BH2) .AND. &
                (pot1%set(i)%gal21%express .EQV. &
                 pot2%set(i)%gal21%express) .AND. &
                (pot1%set(i)%gal21%rcutsq == pot2%set(i)%gal21%rcutsq)) mycompare = .TRUE.

         END SELECT
         mycompare = mycompare .AND. &
                     (pot1%set(i)%rmin == pot2%set(i)%rmin) .AND. (pot1%set(i)%rmax == pot2%set(i)%rmax)
         IF ((mycompare) .AND. (i == 1)) compare = .TRUE.
         compare = compare .AND. mycompare
      END DO

   END SUBROUTINE compare_pot

! **************************************************************************************************
!> \brief Creates the potential parameter type
!> \param potparm ...
!> \param nset ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_single_create(potparm, nset)
      TYPE(pair_potential_single_type), POINTER          :: potparm
      INTEGER, INTENT(IN), OPTIONAL                      :: nset

      INTEGER                                            :: i, lnset

      CPASSERT(.NOT. ASSOCIATED(potparm))
      ALLOCATE (potparm)
      lnset = 1
      IF (PRESENT(nset)) lnset = nset
      ! Standard allocation to size 1
      ALLOCATE (potparm%type(lnset))
      ALLOCATE (potparm%set(lnset))
      NULLIFY (potparm%spl_f, &
               potparm%pair_spline_data)
      DO i = 1, lnset
         potparm%set(i)%rmin = not_initialized
         potparm%set(i)%rmax = not_initialized
         NULLIFY (potparm%set(i)%ipbv, &
                  potparm%set(i)%lj, &
                  potparm%set(i)%gp, &
                  potparm%set(i)%ft, &
                  potparm%set(i)%willis, &
                  potparm%set(i)%goodwin, &
                  potparm%set(i)%eam, &
                  potparm%set(i)%quip, &
                  potparm%set(i)%nequip, &
                  potparm%set(i)%allegro, &
                  potparm%set(i)%deepmd, &
                  potparm%set(i)%buck4r, &
                  potparm%set(i)%buckmo, &
                  potparm%set(i)%tersoff, &
                  potparm%set(i)%siepmann, &
                  potparm%set(i)%gal, &
                  potparm%set(i)%gal21, &
                  potparm%set(i)%ftd, &
                  potparm%set(i)%tab)
      END DO
      CALL pair_potential_single_clean(potparm)
   END SUBROUTINE pair_potential_single_create

! **************************************************************************************************
!> \brief Cleans the potential parameter type
!> \param potparm ...
!> \author unknown
! **************************************************************************************************
   SUBROUTINE pair_potential_single_clean(potparm)
      TYPE(pair_potential_single_type), POINTER          :: potparm

      INTEGER                                            :: i

      potparm%type = nn_type
      potparm%shell_type = nosh_nosh
      potparm%undef = .TRUE.
      potparm%no_pp = .FALSE.
      potparm%no_mb = .FALSE.
      potparm%at1 = 'NULL'
      potparm%at2 = 'NULL'
      potparm%rcutsq = 0.0_dp
      IF (ASSOCIATED(potparm%pair_spline_data)) &
         CALL spline_data_p_release(potparm%pair_spline_data)
      IF (ASSOCIATED(potparm%spl_f)) &
         CALL spline_factor_release(potparm%spl_f)

      DO i = 1, SIZE(potparm%type)
         potparm%set(i)%rmin = not_initialized
         potparm%set(i)%rmax = not_initialized
         CALL pair_potential_lj_clean(potparm%set(i)%lj)
         CALL pair_potential_williams_clean(potparm%set(i)%willis)
         CALL pair_potential_goodwin_clean(potparm%set(i)%goodwin)
         CALL pair_potential_eam_clean(potparm%set(i)%eam)
         CALL pair_potential_quip_clean(potparm%set(i)%quip)
         CALL pair_potential_nequip_clean(potparm%set(i)%nequip)
         CALL pair_potential_allegro_clean(potparm%set(i)%allegro)
         CALL pair_potential_deepmd_clean(potparm%set(i)%deepmd)
         CALL pair_potential_buck4r_clean(potparm%set(i)%buck4r)
         CALL pair_potential_buckmo_clean(potparm%set(i)%buckmo)
         CALL pair_potential_bmhft_clean(potparm%set(i)%ft)
         CALL pair_potential_bmhftd_clean(potparm%set(i)%ftd)
         CALL pair_potential_ipbv_clean(potparm%set(i)%ipbv)
         CALL pair_potential_gp_clean(potparm%set(i)%gp)
         CALL pair_potential_tersoff_clean(potparm%set(i)%tersoff)
         CALL pair_potential_siepmann_clean(potparm%set(i)%siepmann)
         CALL pair_potential_gal_clean(potparm%set(i)%gal)
         CALL pair_potential_gal21_clean(potparm%set(i)%gal21)
         CALL pair_potential_tab_clean(potparm%set(i)%tab)
      END DO
   END SUBROUTINE pair_potential_single_clean

! **************************************************************************************************
!> \brief Copy two potential parameter type
!> \param potparm_source ...
!> \param potparm_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_single_copy(potparm_source, potparm_dest)
      TYPE(pair_potential_single_type), POINTER          :: potparm_source, potparm_dest

      INTEGER                                            :: i

      CPASSERT(ASSOCIATED(potparm_source))
      IF (.NOT. ASSOCIATED(potparm_dest)) THEN
         CALL pair_potential_single_create(potparm_dest, SIZE(potparm_source%type))
      ELSE
         CALL pair_potential_single_clean(potparm_dest)
      END IF
      potparm_dest%type = potparm_source%type
      potparm_dest%shell_type = potparm_source%shell_type
      potparm_dest%undef = potparm_source%undef
      potparm_dest%no_mb = potparm_source%no_mb
      potparm_dest%no_pp = potparm_source%no_pp
      potparm_dest%at1 = potparm_source%at1
      potparm_dest%at2 = potparm_source%at2
      potparm_dest%rcutsq = potparm_source%rcutsq
      IF (ASSOCIATED(potparm_source%pair_spline_data)) THEN
         CALL spline_data_p_copy(potparm_source%pair_spline_data, potparm_dest%pair_spline_data)
      END IF

      IF (ASSOCIATED(potparm_source%spl_f)) THEN
         CALL spline_factor_copy(potparm_source%spl_f, potparm_dest%spl_f)
      END IF

      DO i = 1, SIZE(potparm_source%type)
         potparm_dest%set(i)%rmin = potparm_source%set(i)%rmin
         potparm_dest%set(i)%rmax = potparm_source%set(i)%rmax
         CALL pair_potential_lj_copy(potparm_source%set(i)%lj, potparm_dest%set(i)%lj)
         CALL pair_potential_williams_copy(potparm_source%set(i)%willis, potparm_dest%set(i)%willis)
         CALL pair_potential_goodwin_copy(potparm_source%set(i)%goodwin, potparm_dest%set(i)%goodwin)
         CALL pair_potential_eam_copy(potparm_source%set(i)%eam, potparm_dest%set(i)%eam)
         CALL pair_potential_quip_copy(potparm_source%set(i)%quip, potparm_dest%set(i)%quip)
         CALL pair_potential_nequip_copy(potparm_source%set(i)%nequip, potparm_dest%set(i)%nequip)
         CALL pair_potential_allegro_copy(potparm_source%set(i)%allegro, potparm_dest%set(i)%allegro)
         CALL pair_potential_deepmd_copy(potparm_source%set(i)%deepmd, potparm_dest%set(i)%deepmd)
         CALL pair_potential_bmhft_copy(potparm_source%set(i)%ft, potparm_dest%set(i)%ft)
         CALL pair_potential_bmhftd_copy(potparm_source%set(i)%ftd, potparm_dest%set(i)%ftd)
         CALL pair_potential_ipbv_copy(potparm_source%set(i)%ipbv, potparm_dest%set(i)%ipbv)
         CALL pair_potential_buck4r_copy(potparm_source%set(i)%buck4r, potparm_dest%set(i)%buck4r)
         CALL pair_potential_buckmo_copy(potparm_source%set(i)%buckmo, potparm_dest%set(i)%buckmo)
         CALL pair_potential_gp_copy(potparm_source%set(i)%gp, potparm_dest%set(i)%gp)
         CALL pair_potential_tersoff_copy(potparm_source%set(i)%tersoff, potparm_dest%set(i)%tersoff)
         CALL pair_potential_siepmann_copy(potparm_source%set(i)%siepmann, potparm_dest%set(i)%siepmann)
         CALL pair_potential_gal_copy(potparm_source%set(i)%gal, potparm_dest%set(i)%gal)
         CALL pair_potential_gal21_copy(potparm_source%set(i)%gal21, potparm_dest%set(i)%gal21)
         CALL pair_potential_tab_copy(potparm_source%set(i)%tab, potparm_dest%set(i)%tab)
      END DO
   END SUBROUTINE pair_potential_single_copy

! **************************************************************************************************
!> \brief Add potential parameter type to an existing potential parameter type
!>      Used in case of multiple_potential definition
!> \param potparm_source ...
!> \param potparm_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_single_add(potparm_source, potparm_dest)
      TYPE(pair_potential_single_type), POINTER          :: potparm_source, potparm_dest

      INTEGER                                            :: i, j, size_dest, size_source
      LOGICAL                                            :: allocate_new, check
      TYPE(pair_potential_single_type), POINTER          :: potparm_tmp

      CPASSERT(ASSOCIATED(potparm_source))
      ! At this level we expect all splines types
      ! be not allocated.. No sense add splines at this level.. in case fail!
      check = (.NOT. ASSOCIATED(potparm_source%pair_spline_data)) .AND. &
              (.NOT. ASSOCIATED(potparm_source%spl_f))
      CPASSERT(check)
      check = (.NOT. ASSOCIATED(potparm_dest%pair_spline_data)) .AND. &
              (.NOT. ASSOCIATED(potparm_dest%spl_f))
      CPASSERT(check)
      ! Increase the size of the destination potparm (in case) and copy the new data
      size_source = SIZE(potparm_source%type)
      allocate_new = .NOT. ASSOCIATED(potparm_dest)
      IF (.NOT. allocate_new) THEN
         size_dest = SIZE(potparm_dest%type)
         IF (size_dest == 1) THEN
            check = (ASSOCIATED(potparm_dest%set(1)%lj)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%willis)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%goodwin)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%eam)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%quip)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%nequip)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%allegro)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%deepmd)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%ft)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%ftd)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%ipbv)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%buck4r)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%buckmo)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%gp)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%tersoff)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%siepmann)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%gal)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%gal)) .OR. &
                    (ASSOCIATED(potparm_dest%set(1)%tab))
            IF (.NOT. check) THEN
               allocate_new = .TRUE.
               CALL pair_potential_single_release(potparm_dest)
            END IF
         END IF
      END IF
      IF (allocate_new) THEN
         size_dest = 0
         CALL pair_potential_single_create(potparm_dest, size_source)
         potparm_dest%shell_type = potparm_source%shell_type
         potparm_dest%undef = potparm_source%undef
         potparm_dest%no_mb = potparm_source%no_mb
         potparm_dest%no_pp = potparm_source%no_pp
         potparm_dest%at1 = potparm_source%at1
         potparm_dest%at2 = potparm_source%at2
         potparm_dest%rcutsq = potparm_source%rcutsq
      ELSE
         size_dest = SIZE(potparm_dest%type)
         NULLIFY (potparm_tmp)
         CALL pair_potential_single_copy(potparm_dest, potparm_tmp)
         CALL pair_potential_single_release(potparm_dest)
         CALL pair_potential_single_create(potparm_dest, size_dest + size_source)
         ! Copy back original informations..
         potparm_dest%shell_type = potparm_tmp%shell_type
         potparm_dest%undef = potparm_tmp%undef
         potparm_dest%no_mb = potparm_tmp%no_mb
         potparm_dest%no_pp = potparm_tmp%no_pp
         potparm_dest%at1 = potparm_tmp%at1
         potparm_dest%at2 = potparm_tmp%at2
         potparm_dest%rcutsq = potparm_tmp%rcutsq
         DO i = 1, size_dest
            potparm_dest%type(i) = potparm_tmp%type(i)
            potparm_dest%set(i)%rmin = potparm_tmp%set(i)%rmin
            potparm_dest%set(i)%rmax = potparm_tmp%set(i)%rmax
            CALL pair_potential_lj_copy(potparm_tmp%set(i)%lj, potparm_dest%set(i)%lj)
            CALL pair_potential_williams_copy(potparm_tmp%set(i)%willis, potparm_dest%set(i)%willis)
            CALL pair_potential_goodwin_copy(potparm_tmp%set(i)%goodwin, potparm_dest%set(i)%goodwin)
            CALL pair_potential_eam_copy(potparm_tmp%set(i)%eam, potparm_dest%set(i)%eam)
            CALL pair_potential_quip_copy(potparm_tmp%set(i)%quip, potparm_dest%set(i)%quip)
            CALL pair_potential_nequip_copy(potparm_tmp%set(i)%nequip, potparm_dest%set(i)%nequip)
            CALL pair_potential_allegro_copy(potparm_tmp%set(i)%allegro, potparm_dest%set(i)%allegro)
            CALL pair_potential_deepmd_copy(potparm_tmp%set(i)%deepmd, potparm_dest%set(i)%deepmd)
            CALL pair_potential_bmhft_copy(potparm_tmp%set(i)%ft, potparm_dest%set(i)%ft)
            CALL pair_potential_bmhftd_copy(potparm_tmp%set(i)%ftd, potparm_dest%set(i)%ftd)
            CALL pair_potential_ipbv_copy(potparm_tmp%set(i)%ipbv, potparm_dest%set(i)%ipbv)
            CALL pair_potential_buck4r_copy(potparm_tmp%set(i)%buck4r, potparm_dest%set(i)%buck4r)
            CALL pair_potential_buckmo_copy(potparm_tmp%set(i)%buckmo, potparm_dest%set(i)%buckmo)
            CALL pair_potential_gp_copy(potparm_tmp%set(i)%gp, potparm_dest%set(i)%gp)
            CALL pair_potential_tersoff_copy(potparm_tmp%set(i)%tersoff, potparm_dest%set(i)%tersoff)
            CALL pair_potential_siepmann_copy(potparm_tmp%set(i)%siepmann, potparm_dest%set(i)%siepmann)
            CALL pair_potential_gal_copy(potparm_tmp%set(i)%gal, potparm_dest%set(i)%gal)
            CALL pair_potential_gal21_copy(potparm_tmp%set(i)%gal21, potparm_dest%set(i)%gal21)
            CALL pair_potential_tab_copy(potparm_tmp%set(i)%tab, potparm_dest%set(i)%tab)
         END DO
         CALL pair_potential_single_release(potparm_tmp)
      END IF
      ! Further check with main option with source and dest (already filled with few informations)
      check = (potparm_dest%shell_type == potparm_source%shell_type) .AND. &
              (potparm_dest%undef .EQV. potparm_source%undef) .AND. &
              (potparm_dest%no_mb .EQV. potparm_source%no_mb) .AND. &
              (potparm_dest%no_pp .EQV. potparm_source%no_pp) .AND. &
              (potparm_dest%at1 == potparm_source%at1) .AND. &
              (potparm_dest%at2 == potparm_source%at2) .AND. &
              (potparm_dest%rcutsq == potparm_source%rcutsq)
      CPASSERT(check)
      ! Now copy the new pair_potential type
      DO i = size_dest + 1, size_dest + size_source
         j = i - size_dest
         potparm_dest%type(i) = potparm_source%type(j)
         potparm_dest%set(i)%rmin = potparm_source%set(j)%rmin
         potparm_dest%set(i)%rmax = potparm_source%set(j)%rmax
         CALL pair_potential_lj_copy(potparm_source%set(j)%lj, potparm_dest%set(i)%lj)
         CALL pair_potential_williams_copy(potparm_source%set(j)%willis, potparm_dest%set(i)%willis)
         CALL pair_potential_goodwin_copy(potparm_source%set(j)%goodwin, potparm_dest%set(i)%goodwin)
         CALL pair_potential_eam_copy(potparm_source%set(j)%eam, potparm_dest%set(i)%eam)
         CALL pair_potential_quip_copy(potparm_source%set(j)%quip, potparm_dest%set(i)%quip)
         CALL pair_potential_nequip_copy(potparm_source%set(j)%nequip, potparm_dest%set(i)%nequip)
         CALL pair_potential_allegro_copy(potparm_source%set(j)%allegro, potparm_dest%set(i)%allegro)
         CALL pair_potential_deepmd_copy(potparm_source%set(j)%deepmd, potparm_dest%set(i)%deepmd)
         CALL pair_potential_bmhft_copy(potparm_source%set(j)%ft, potparm_dest%set(i)%ft)
         CALL pair_potential_bmhftd_copy(potparm_source%set(j)%ftd, potparm_dest%set(i)%ftd)
         CALL pair_potential_ipbv_copy(potparm_source%set(j)%ipbv, potparm_dest%set(i)%ipbv)
         CALL pair_potential_buck4r_copy(potparm_source%set(j)%buck4r, potparm_dest%set(i)%buck4r)
         CALL pair_potential_buckmo_copy(potparm_source%set(j)%buckmo, potparm_dest%set(i)%buckmo)
         CALL pair_potential_gp_copy(potparm_source%set(j)%gp, potparm_dest%set(i)%gp)
         CALL pair_potential_tersoff_copy(potparm_source%set(j)%tersoff, potparm_dest%set(i)%tersoff)
         CALL pair_potential_siepmann_copy(potparm_source%set(j)%siepmann, potparm_dest%set(i)%siepmann)
         CALL pair_potential_gal_copy(potparm_source%set(j)%gal, potparm_dest%set(i)%gal)
         CALL pair_potential_gal21_copy(potparm_source%set(j)%gal21, potparm_dest%set(i)%gal21)
         CALL pair_potential_tab_copy(potparm_source%set(j)%tab, potparm_dest%set(i)%tab)
      END DO
   END SUBROUTINE pair_potential_single_add

! **************************************************************************************************
!> \brief Release Data-structure that constains potential parameters of a single pair
!> \param potparm ...
!> \author Teodoro Laino [Teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_single_release(potparm)
      TYPE(pair_potential_single_type), POINTER          :: potparm

      INTEGER                                            :: i

      CPASSERT(ASSOCIATED(potparm))
      CALL spline_data_p_release(potparm%pair_spline_data)
      CALL spline_factor_release(potparm%spl_f)
      DO i = 1, SIZE(potparm%type)
         CALL pair_potential_ipbv_release(potparm%set(i)%ipbv)
         CALL pair_potential_lj_release(potparm%set(i)%lj)
         CALL pair_potential_bmhft_release(potparm%set(i)%ft)
         CALL pair_potential_bmhftd_release(potparm%set(i)%ftd)
         CALL pair_potential_williams_release(potparm%set(i)%willis)
         CALL pair_potential_goodwin_release(potparm%set(i)%goodwin)
         CALL pair_potential_eam_release(potparm%set(i)%eam)
         CALL pair_potential_quip_release(potparm%set(i)%quip)
         CALL pair_potential_nequip_release(potparm%set(i)%nequip)
         CALL pair_potential_allegro_release(potparm%set(i)%allegro)
         CALL pair_potential_deepmd_release(potparm%set(i)%deepmd)
         CALL pair_potential_buck4r_release(potparm%set(i)%buck4r)
         CALL pair_potential_buckmo_release(potparm%set(i)%buckmo)
         CALL pair_potential_gp_release(potparm%set(i)%gp)
         CALL pair_potential_tersoff_release(potparm%set(i)%tersoff)
         CALL pair_potential_siepmann_release(potparm%set(i)%siepmann)
         CALL pair_potential_gal_release(potparm%set(i)%gal)
         CALL pair_potential_gal21_release(potparm%set(i)%gal21)
         CALL pair_potential_tab_release(potparm%set(i)%tab)
      END DO
      DEALLOCATE (potparm%type)
      DEALLOCATE (potparm%set)
      DEALLOCATE (potparm)
   END SUBROUTINE pair_potential_single_release

! **************************************************************************************************
!> \brief Data-structure that constains potential parameters
!> \param potparm ...
!> \param nkinds ...
!> \author unknown
! **************************************************************************************************
   SUBROUTINE pair_potential_pp_create(potparm, nkinds)
      TYPE(pair_potential_pp_type), POINTER              :: potparm
      INTEGER, INTENT(IN)                                :: nkinds

      INTEGER                                            :: i, j

      CPASSERT(.NOT. ASSOCIATED(potparm))
      ALLOCATE (potparm)
      ALLOCATE (potparm%pot(nkinds, nkinds))
      DO i = 1, nkinds
         DO j = 1, nkinds
            NULLIFY (potparm%pot(i, j)%pot)
         END DO
      END DO
      ! Use no-redundancy in the potential definition
      DO i = 1, nkinds
         DO j = i, nkinds
            CALL pair_potential_single_create(potparm%pot(i, j)%pot)
            potparm%pot(j, i)%pot => potparm%pot(i, j)%pot
         END DO
      END DO
   END SUBROUTINE pair_potential_pp_create

! **************************************************************************************************
!> \brief Release Data-structure that constains potential parameters
!> \param potparm ...
!> \par History
!>      Teodoro Laino [Teo] 11.2005 : Reorganizing the structures to optimize
!>                                    memory management
!> \author unknown
! **************************************************************************************************
   SUBROUTINE pair_potential_pp_release(potparm)
      TYPE(pair_potential_pp_type), POINTER              :: potparm

      INTEGER                                            :: i, j

      IF (ASSOCIATED(potparm)) THEN
         IF (ASSOCIATED(potparm%pot)) THEN
            DO i = 1, SIZE(potparm%pot, 1)
               DO j = i, SIZE(potparm%pot, 2)
                  CALL pair_potential_single_release(potparm%pot(i, j)%pot)
                  NULLIFY (potparm%pot(j, i)%pot)
               END DO
            END DO
            DEALLOCATE (potparm%pot)
         END IF
         DEALLOCATE (potparm)
      END IF
      NULLIFY (potparm)
   END SUBROUTINE pair_potential_pp_release

! **************************************************************************************************
!> \brief Data-structure that constains potential parameters
!> \param potparm ...
!> \param ndim ...
!> \param ub ...
!> \param lb ...
!> \author unknown
! **************************************************************************************************
   SUBROUTINE pair_potential_p_create(potparm, ndim, ub, lb)
      TYPE(pair_potential_p_type), POINTER               :: potparm
      INTEGER, INTENT(IN), OPTIONAL                      :: ndim, ub, lb

      INTEGER                                            :: i, loc_lb, loc_ub

      CPASSERT(.NOT. ASSOCIATED(potparm))
      ALLOCATE (potparm)
      IF (PRESENT(ndim)) THEN
         loc_lb = 1
         loc_ub = ndim
         ALLOCATE (potparm%pot(loc_lb:loc_ub))
         IF (PRESENT(lb) .OR. PRESENT(ub)) THEN
            CPABORT("")
         END IF
      ELSE IF (PRESENT(lb) .AND. PRESENT(ub)) THEN
         loc_lb = lb
         loc_ub = ub
         ALLOCATE (potparm%pot(loc_lb:loc_ub))
         IF (PRESENT(ndim)) THEN
            CPABORT("")
         END IF
      ELSE
         CPABORT("")
      END IF
      DO i = loc_lb, loc_ub
         NULLIFY (potparm%pot(i)%pot)
         CALL pair_potential_single_create(potparm%pot(i)%pot)
      END DO
   END SUBROUTINE pair_potential_p_create

! **************************************************************************************************
!> \brief Release Data-structure that constains potential parameters
!> \param potparm ...
!> \par History
!>      Teodoro Laino [Teo] 11.2005 : Reorganizing the structures to optimize
!>                                    memory management
!> \author unknown
! **************************************************************************************************
   SUBROUTINE pair_potential_p_release(potparm)
      TYPE(pair_potential_p_type), POINTER               :: potparm

      INTEGER                                            :: i

      IF (ASSOCIATED(potparm)) THEN
         IF (ASSOCIATED(potparm%pot)) THEN
            DO i = 1, SIZE(potparm%pot)
               CALL pair_potential_single_release(potparm%pot(i)%pot)
            END DO
            DEALLOCATE (potparm%pot)
         END IF
         DEALLOCATE (potparm)
      END IF
      NULLIFY (potparm)
   END SUBROUTINE pair_potential_p_release

! **************************************************************************************************
!> \brief Copy structures between two pair_potential_p_type
!> \param source ...
!> \param dest ...
!> \param istart ...
!> \param iend ...
!> \author Teodoro Laino [Teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_p_copy(source, dest, istart, iend)
      TYPE(pair_potential_p_type), POINTER               :: source, dest
      INTEGER, INTENT(IN), OPTIONAL                      :: istart, iend

      INTEGER                                            :: i, l_end, l_start

      CPASSERT(ASSOCIATED(source))
      CPASSERT(ASSOCIATED(dest))
      l_start = LBOUND(source%pot, 1)
      l_end = UBOUND(source%pot, 1)
      IF (PRESENT(istart)) l_start = istart
      IF (PRESENT(iend)) l_end = iend
      DO i = l_start, l_end
         IF (.NOT. ASSOCIATED(source%pot(i)%pot)) &
            CALL pair_potential_single_create(source%pot(i)%pot)
         CALL pair_potential_single_copy(source%pot(i)%pot, dest%pot(i)%pot)
      END DO
   END SUBROUTINE pair_potential_p_copy

! **************************************************************************************************
!> \brief Cleans the potential parameter type
!> \param p ...
!> \param lb1_new ...
!> \param ub1_new ...
!> \param lj ...
!> \param lj_charmm ...
!> \param williams ...
!> \param goodwin ...
!> \param eam ...
!> \param quip ...
!> \param nequip ...
!> \param allegro ...
!> \param bmhft ...
!> \param bmhftd ...
!> \param ipbv ...
!> \param buck4r ...
!> \param buckmo ...
!> \param gp ...
!> \param tersoff ...
!> \param siepmann ...
!> \param gal ...
!> \param gal21 ...
!> \param tab ...
!> \param deepmd ...
!> \author Teodoro Laino [Teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_reallocate(p, lb1_new, ub1_new, lj, lj_charmm, williams, goodwin, eam, &
                                        quip, nequip, allegro, bmhft, bmhftd, ipbv, buck4r, buckmo, &
                                        gp, tersoff, siepmann, gal, gal21, tab, deepmd)
      TYPE(pair_potential_p_type), POINTER               :: p
      INTEGER, INTENT(IN)                                :: lb1_new, ub1_new
      LOGICAL, INTENT(IN), OPTIONAL :: lj, lj_charmm, williams, goodwin, eam, quip, nequip, &
         allegro, bmhft, bmhftd, ipbv, buck4r, buckmo, gp, tersoff, siepmann, gal, gal21, tab, &
         deepmd

      INTEGER                                            :: i, ipot, lb1_old, std_dim, ub1_old
      LOGICAL :: check, lallegro, lbmhft, lbmhftd, lbuck4r, lbuckmo, ldeepmd, leam, lgal, lgal21, &
         lgoodwin, lgp, lipbv, llj, llj_charmm, lnequip, lquip, lsiepmann, ltab, ltersoff, &
         lwilliams
      TYPE(pair_potential_p_type), POINTER               :: work

      NULLIFY (work)
      ipot = 0
      llj = .FALSE.; IF (PRESENT(lj)) llj = lj
      llj_charmm = .FALSE.; IF (PRESENT(lj_charmm)) llj_charmm = lj_charmm
      lwilliams = .FALSE.; IF (PRESENT(williams)) lwilliams = williams
      lgoodwin = .FALSE.; IF (PRESENT(goodwin)) lgoodwin = goodwin
      leam = .FALSE.; IF (PRESENT(eam)) leam = eam
      lquip = .FALSE.; IF (PRESENT(quip)) lquip = quip
      lnequip = .FALSE.; IF (PRESENT(nequip)) lnequip = nequip
      lallegro = .FALSE.; IF (PRESENT(allegro)) lallegro = allegro
      ldeepmd = .FALSE.; IF (PRESENT(deepmd)) ldeepmd = deepmd
      lbmhft = .FALSE.; IF (PRESENT(bmhft)) lbmhft = bmhft
      lbmhftd = .FALSE.; IF (PRESENT(bmhftd)) lbmhftd = bmhftd
      lipbv = .FALSE.; IF (PRESENT(ipbv)) lipbv = ipbv
      lbuck4r = .FALSE.; IF (PRESENT(buck4r)) lbuck4r = buck4r
      lbuckmo = .FALSE.; IF (PRESENT(buckmo)) lbuckmo = buckmo
      lgp = .FALSE.; IF (PRESENT(gp)) lgp = gp
      ltersoff = .FALSE.; IF (PRESENT(tersoff)) ltersoff = tersoff
      lsiepmann = .FALSE.; IF (PRESENT(siepmann)) lsiepmann = siepmann
      lgal = .FALSE.; IF (PRESENT(gal)) lgal = gal
      lgal21 = .FALSE.; IF (PRESENT(gal21)) lgal21 = gal21
      ltab = .FALSE.; IF (PRESENT(tab)) ltab = tab

      IF (llj) THEN
         ipot = lj_type
         check = .NOT. (llj_charmm .OR. lwilliams .OR. lgoodwin .OR. leam .OR. lquip .OR. lnequip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (llj_charmm) THEN
         ipot = lj_charmm_type
         check = .NOT. (llj .OR. lwilliams .OR. lgoodwin .OR. leam .OR. lquip .OR. lnequip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lwilliams) THEN
         ipot = wl_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. leam .OR. lquip .OR. lnequip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lgoodwin) THEN
         ipot = gw_type
         check = .NOT. (llj .OR. llj_charmm .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (leam) THEN
         ipot = ea_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. lquip .OR. lnequip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lquip) THEN
         ipot = quip_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lnequip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lnequip) THEN
         ipot = nequip_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lallegro &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lallegro) THEN
         ipot = allegro_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (ldeepmd) THEN
         ipot = deepmd_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp &
                        .OR. ltersoff .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab)
         CPASSERT(check)
      END IF
      IF (lbmhft) THEN
         ipot = ft_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lbmhftd) THEN
         ipot = ftd_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lipbv .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lipbv) THEN
         ipot = ip_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lbuck4r .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lbuck4r) THEN
         ipot = b4_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuckmo .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lbuckmo) THEN
         ipot = bm_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. ltersoff &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (ltersoff) THEN
         ipot = tersoff_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
                        .OR. lsiepmann .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lsiepmann) THEN
         ipot = siepmann_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
                        .OR. ltersoff .OR. lgal .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lgal) THEN
         ipot = gal_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
                        .OR. ltersoff .OR. lsiepmann .OR. lgal21 .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lgal21) THEN
         ipot = gal21_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lbuckmo &
                        .OR. ltersoff .OR. lsiepmann .OR. lgal .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (lgp) THEN
         ipot = gp_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgal21 .OR. lbuckmo &
                        .OR. ltersoff .OR. lsiepmann .OR. lgal .OR. ltab .OR. ldeepmd)
         CPASSERT(check)
      END IF
      IF (ltab) THEN
         ipot = tab_type
         check = .NOT. (llj .OR. llj_charmm .OR. lgoodwin .OR. lwilliams .OR. leam .OR. lquip .OR. lnequip &
                        .OR. lallegro .OR. lbmhft .OR. lbmhftd .OR. lipbv .OR. lbuck4r .OR. lgp .OR. lgal21 &
                        .OR. lbuckmo .OR. ltersoff .OR. lsiepmann .OR. lgal)
         CPASSERT(check)
      END IF

      lb1_old = 0
      ub1_old = 0
      IF (ASSOCIATED(p)) THEN
         lb1_old = LBOUND(p%pot, 1)
         ub1_old = UBOUND(p%pot, 1)
         CALL pair_potential_p_create(work, lb=lb1_old, ub=ub1_old)
         CALL pair_potential_p_copy(p, work)
         CALL pair_potential_p_release(p)
      END IF

      CALL pair_potential_p_create(p, lb=lb1_new, ub=ub1_new)
      IF (ASSOCIATED(work)) THEN
         CALL pair_potential_p_copy(work, p, istart=lb1_old, iend=ub1_old)
      END IF
      std_dim = 1
      DO i = ub1_old + 1, ub1_new
         check = (SIZE(p%pot(i)%pot%type) == std_dim) .AND. (SIZE(p%pot(i)%pot%type) == std_dim)
         CPASSERT(check)
         p%pot(i)%pot%type = nn_type
         p%pot(i)%pot%shell_type = nosh_nosh
         p%pot(i)%pot%undef = .TRUE.
         p%pot(i)%pot%no_mb = .FALSE.
         p%pot(i)%pot%no_pp = .FALSE.
         p%pot(i)%pot%at1 = 'NULL'
         p%pot(i)%pot%at2 = 'NULL'
         p%pot(i)%pot%set(std_dim)%rmin = not_initialized
         p%pot(i)%pot%set(std_dim)%rmax = not_initialized
         SELECT CASE (ipot)
         CASE (lj_type, lj_charmm_type)
            CALL pair_potential_lj_create(p%pot(i)%pot%set(std_dim)%lj)
         CASE (wl_type)
            CALL pair_potential_williams_create(p%pot(i)%pot%set(std_dim)%willis)
         CASE (gw_type)
            CALL pair_potential_goodwin_create(p%pot(i)%pot%set(std_dim)%goodwin)
         CASE (ea_type)
            CALL pair_potential_eam_create(p%pot(i)%pot%set(std_dim)%eam)
         CASE (quip_type)
            CALL pair_potential_quip_create(p%pot(i)%pot%set(std_dim)%quip)
         CASE (nequip_type)
            CALL pair_potential_nequip_create(p%pot(i)%pot%set(std_dim)%nequip)
         CASE (allegro_type)
            CALL pair_potential_allegro_create(p%pot(i)%pot%set(std_dim)%allegro)
         CASE (deepmd_type)
            CALL pair_potential_deepmd_create(p%pot(i)%pot%set(std_dim)%deepmd)
         CASE (ft_type)
            CALL pair_potential_bmhft_create(p%pot(i)%pot%set(std_dim)%ft)
         CASE (ftd_type)
            CALL pair_potential_bmhftd_create(p%pot(i)%pot%set(std_dim)%ftd)
         CASE (ip_type)
            CALL pair_potential_ipbv_create(p%pot(i)%pot%set(std_dim)%ipbv)
         CASE (b4_type)
            CALL pair_potential_buck4r_create(p%pot(i)%pot%set(std_dim)%buck4r)
         CASE (bm_type)
            CALL pair_potential_buckmo_create(p%pot(i)%pot%set(std_dim)%buckmo)
         CASE (gp_type)
            CALL pair_potential_gp_create(p%pot(i)%pot%set(std_dim)%gp)
         CASE (tersoff_type)
            CALL pair_potential_tersoff_create(p%pot(i)%pot%set(std_dim)%tersoff)
         CASE (siepmann_type)
            CALL pair_potential_siepmann_create(p%pot(i)%pot%set(std_dim)%siepmann)
         CASE (gal_type)
            CALL pair_potential_gal_create(p%pot(i)%pot%set(std_dim)%gal)
         CASE (gal21_type)
            CALL pair_potential_gal21_create(p%pot(i)%pot%set(std_dim)%gal21)
         CASE (tab_type)
            CALL pair_potential_tab_create(p%pot(i)%pot%set(std_dim)%tab)
         END SELECT
         NULLIFY (p%pot(i)%pot%spl_f)
         NULLIFY (p%pot(i)%pot%pair_spline_data)
      END DO

      IF (ASSOCIATED(work)) CALL pair_potential_p_release(work)
   END SUBROUTINE pair_potential_reallocate

! **************************************************************************************************
!> \brief Creates the generic potential type
!> \param gp ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_gp_create(gp)
      TYPE(gp_pot_type), POINTER                         :: gp

      CPASSERT(.NOT. ASSOCIATED(gp))
      ALLOCATE (gp)
      NULLIFY (gp%parameters)
      NULLIFY (gp%values)
      CALL pair_potential_gp_clean(gp)
   END SUBROUTINE pair_potential_gp_create

! **************************************************************************************************
!> \brief Copy two generic potential type
!> \param gp_source ...
!> \param gp_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_gp_copy(gp_source, gp_dest)
      TYPE(gp_pot_type), POINTER                         :: gp_source, gp_dest

      INTEGER                                            :: idim

      IF (.NOT. ASSOCIATED(gp_source)) RETURN
      IF (ASSOCIATED(gp_dest)) CALL pair_potential_gp_release(gp_dest)
      CALL pair_potential_gp_create(gp_dest)
      gp_dest%myid = gp_source%myid
      gp_dest%potential = gp_source%potential
      gp_dest%variables = gp_source%variables
      IF (ASSOCIATED(gp_source%parameters)) THEN
         idim = SIZE(gp_source%parameters)
         ALLOCATE (gp_dest%parameters(idim))
         gp_dest%parameters = gp_source%parameters
      END IF
      IF (ASSOCIATED(gp_source%values)) THEN
         idim = SIZE(gp_source%values)
         ALLOCATE (gp_dest%values(idim))
         gp_dest%values = gp_source%values
      END IF
   END SUBROUTINE pair_potential_gp_copy

! **************************************************************************************************
!> \brief Cleans the generic potential type
!> \param gp ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_gp_clean(gp)
      TYPE(gp_pot_type), POINTER                         :: gp

      IF (.NOT. ASSOCIATED(gp)) RETURN
      gp%myid = 0
      gp%potential = ""
      gp%variables = ""
      IF (ASSOCIATED(gp%values)) THEN
         DEALLOCATE (gp%values)
      END IF
      IF (ASSOCIATED(gp%parameters)) THEN
         DEALLOCATE (gp%parameters)
      END IF
   END SUBROUTINE pair_potential_gp_clean

! **************************************************************************************************
!> \brief Destroys the generic potential type
!> \param gp ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_gp_release(gp)
      TYPE(gp_pot_type), POINTER                         :: gp

      IF (ASSOCIATED(gp)) THEN
         IF (ASSOCIATED(gp%parameters)) THEN
            DEALLOCATE (gp%parameters)
         END IF
         IF (ASSOCIATED(gp%values)) THEN
            DEALLOCATE (gp%values)
         END IF
         DEALLOCATE (gp)
      END IF
      NULLIFY (gp)
   END SUBROUTINE pair_potential_gp_release

! **************************************************************************************************
!> \brief Cleans the LJ potential type
!> \param lj ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_lj_create(lj)
      TYPE(lj_pot_type), POINTER                         :: lj

      CPASSERT(.NOT. ASSOCIATED(lj))
      ALLOCATE (lj)
      CALL pair_potential_lj_clean(lj)
   END SUBROUTINE pair_potential_lj_create

! **************************************************************************************************
!> \brief Copy two LJ potential type
!> \param lj_source ...
!> \param lj_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_lj_copy(lj_source, lj_dest)
      TYPE(lj_pot_type), POINTER                         :: lj_source, lj_dest

      IF (.NOT. ASSOCIATED(lj_source)) RETURN
      IF (ASSOCIATED(lj_dest)) CALL pair_potential_lj_release(lj_dest)
      CALL pair_potential_lj_create(lj_dest)
      lj_dest%epsilon = lj_source%epsilon
      lj_dest%sigma6 = lj_source%sigma6
      lj_dest%sigma12 = lj_source%sigma12
   END SUBROUTINE pair_potential_lj_copy

! **************************************************************************************************
!> \brief Creates the LJ potential type
!> \param lj ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_lj_clean(lj)
      TYPE(lj_pot_type), POINTER                         :: lj

      IF (.NOT. ASSOCIATED(lj)) RETURN
      lj%epsilon = 0.0_dp
      lj%sigma6 = 0.0_dp
      lj%sigma12 = 0.0_dp
   END SUBROUTINE pair_potential_lj_clean

! **************************************************************************************************
!> \brief Destroys the LJ potential type
!> \param lj ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_lj_release(lj)
      TYPE(lj_pot_type), POINTER                         :: lj

      IF (ASSOCIATED(lj)) THEN
         DEALLOCATE (lj)
      END IF
      NULLIFY (lj)
   END SUBROUTINE pair_potential_lj_release

! **************************************************************************************************
!> \brief Creates the WILLIAMS potential type
!> \param willis ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_williams_create(willis)
      TYPE(williams_pot_type), POINTER                   :: willis

      CPASSERT(.NOT. ASSOCIATED(willis))
      ALLOCATE (willis)
      CALL pair_potential_williams_clean(willis)
   END SUBROUTINE pair_potential_williams_create

! **************************************************************************************************
!> \brief Copy two WILLIAMS potential type
!> \param willis_source ...
!> \param willis_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_williams_copy(willis_source, willis_dest)
      TYPE(williams_pot_type), POINTER                   :: willis_source, willis_dest

      IF (.NOT. ASSOCIATED(willis_source)) RETURN
      IF (ASSOCIATED(willis_dest)) CALL pair_potential_williams_release(willis_dest)
      CALL pair_potential_williams_create(willis_dest)
      willis_dest%a = willis_source%a
      willis_dest%b = willis_source%b
      willis_dest%c = willis_source%c
   END SUBROUTINE pair_potential_williams_copy

! **************************************************************************************************
!> \brief Creates the WILLIAMS potential type
!> \param willis ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_williams_clean(willis)
      TYPE(williams_pot_type), POINTER                   :: willis

      IF (.NOT. ASSOCIATED(willis)) RETURN
      willis%a = 0.0_dp
      willis%b = 0.0_dp
      willis%c = 0.0_dp
   END SUBROUTINE pair_potential_williams_clean

! **************************************************************************************************
!> \brief Destroys the WILLIAMS potential type
!> \param willis ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_williams_release(willis)
      TYPE(williams_pot_type), POINTER                   :: willis

      IF (ASSOCIATED(willis)) THEN
         DEALLOCATE (willis)
      END IF
      NULLIFY (willis)
   END SUBROUTINE pair_potential_williams_release

! **************************************************************************************************
!> \brief Creates the GOODWIN potential type
!> \param goodwin ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_goodwin_create(goodwin)
      TYPE(goodwin_pot_type), POINTER                    :: goodwin

      CPASSERT(.NOT. ASSOCIATED(goodwin))
      ALLOCATE (goodwin)
      CALL pair_potential_goodwin_clean(goodwin)
   END SUBROUTINE pair_potential_goodwin_create

! **************************************************************************************************
!> \brief Copy two GOODWIN potential type
!> \param goodwin_source ...
!> \param goodwin_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_goodwin_copy(goodwin_source, goodwin_dest)
      TYPE(goodwin_pot_type), POINTER                    :: goodwin_source, goodwin_dest

      IF (.NOT. ASSOCIATED(goodwin_source)) RETURN
      IF (ASSOCIATED(goodwin_dest)) CALL pair_potential_goodwin_release(goodwin_dest)
      CALL pair_potential_goodwin_create(goodwin_dest)
      goodwin_dest%vr0 = goodwin_source%vr0
      goodwin_dest%d = goodwin_source%d
      goodwin_dest%dc = goodwin_source%dc
      goodwin_dest%m = goodwin_source%m
      goodwin_dest%mc = goodwin_source%mc
   END SUBROUTINE pair_potential_goodwin_copy

! **************************************************************************************************
!> \brief Creates the GOODWIN potential type
!> \param goodwin ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_goodwin_clean(goodwin)
      TYPE(goodwin_pot_type), POINTER                    :: goodwin

      IF (.NOT. ASSOCIATED(goodwin)) RETURN
      goodwin%vr0 = 0.0_dp
      goodwin%d = 0.0_dp
      goodwin%dc = 0.0_dp
      goodwin%m = 0.0_dp
      goodwin%mc = 0.0_dp
   END SUBROUTINE pair_potential_goodwin_clean

! **************************************************************************************************
!> \brief Destroys the GOODWIN potential type
!> \param goodwin ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_goodwin_release(goodwin)
      TYPE(goodwin_pot_type), POINTER                    :: goodwin

      IF (ASSOCIATED(goodwin)) THEN
         DEALLOCATE (goodwin)
      END IF
      NULLIFY (goodwin)
   END SUBROUTINE pair_potential_goodwin_release

! **************************************************************************************************
!> \brief Creates the EAM potential type
!> \param eam ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_eam_create(eam)
      TYPE(eam_pot_type), POINTER                        :: eam

      CPASSERT(.NOT. ASSOCIATED(eam))
      ALLOCATE (eam)
      NULLIFY (eam%rho, eam%phi, eam%frho, eam%rhoval, eam%rval, &
               eam%rhop, eam%phip, eam%frhop)
      CALL pair_potential_eam_clean(eam)
   END SUBROUTINE pair_potential_eam_create

! **************************************************************************************************
!> \brief Copy two EAM potential type
!> \param eam_source ...
!> \param eam_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_eam_copy(eam_source, eam_dest)
      TYPE(eam_pot_type), POINTER                        :: eam_source, eam_dest

      IF (.NOT. ASSOCIATED(eam_source)) RETURN
      IF (ASSOCIATED(eam_dest)) CALL pair_potential_eam_release(eam_dest)
      CALL pair_potential_eam_create(eam_dest)
      eam_dest%eam_file_name = eam_source%eam_file_name
      eam_dest%drar = eam_source%drar
      eam_dest%drhoar = eam_source%drhoar
      eam_dest%acutal = eam_source%acutal
      eam_dest%npoints = eam_source%npoints
      ! Allocate arrays with the proper size
      CALL reallocate(eam_dest%rho, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%rhop, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%phi, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%phip, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%frho, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%frhop, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%rval, 1, eam_dest%npoints)
      CALL reallocate(eam_dest%rhoval, 1, eam_dest%npoints)
      eam_dest%rho = eam_source%rho
      eam_dest%phi = eam_source%phi
      eam_dest%frho = eam_source%frho
      eam_dest%rhoval = eam_source%rhoval
      eam_dest%rval = eam_source%rval
      eam_dest%rhop = eam_source%rhop
      eam_dest%phip = eam_source%phip
      eam_dest%frhop = eam_source%frhop
   END SUBROUTINE pair_potential_eam_copy

! **************************************************************************************************
!> \brief Creates the EAM potential type
!> \param eam ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_eam_clean(eam)
      TYPE(eam_pot_type), POINTER                        :: eam

      IF (.NOT. ASSOCIATED(eam)) RETURN
      eam%eam_file_name = 'NULL'
      eam%drar = 0.0_dp
      eam%drhoar = 0.0_dp
      eam%acutal = 0.0_dp
      eam%npoints = 0
      CALL reallocate(eam%rho, 1, eam%npoints)
      CALL reallocate(eam%rhop, 1, eam%npoints)
      CALL reallocate(eam%phi, 1, eam%npoints)
      CALL reallocate(eam%phip, 1, eam%npoints)
      CALL reallocate(eam%frho, 1, eam%npoints)
      CALL reallocate(eam%frhop, 1, eam%npoints)
      CALL reallocate(eam%rval, 1, eam%npoints)
      CALL reallocate(eam%rhoval, 1, eam%npoints)
   END SUBROUTINE pair_potential_eam_clean

! **************************************************************************************************
!> \brief Destroys the EAM potential type
!> \param eam ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_eam_release(eam)
      TYPE(eam_pot_type), POINTER                        :: eam

      IF (ASSOCIATED(eam)) THEN
         IF (ASSOCIATED(eam%rho)) THEN
            DEALLOCATE (eam%rho)
         END IF
         IF (ASSOCIATED(eam%rhop)) THEN
            DEALLOCATE (eam%rhop)
         END IF
         IF (ASSOCIATED(eam%phi)) THEN
            DEALLOCATE (eam%phi)
         END IF
         IF (ASSOCIATED(eam%phip)) THEN
            DEALLOCATE (eam%phip)
         END IF
         IF (ASSOCIATED(eam%frho)) THEN
            DEALLOCATE (eam%frho)
         END IF
         IF (ASSOCIATED(eam%frhop)) THEN
            DEALLOCATE (eam%frhop)
         END IF
         IF (ASSOCIATED(eam%rval)) THEN
            DEALLOCATE (eam%rval)
         END IF
         IF (ASSOCIATED(eam%rhoval)) THEN
            DEALLOCATE (eam%rhoval)
         END IF
         DEALLOCATE (eam)
      END IF
   END SUBROUTINE pair_potential_eam_release

! **************************************************************************************************
!> \brief Creates the DEEPMD potential type
!> \param deepmd ...
!> \author Yongbin Zhuang 07.2019
! **************************************************************************************************
   SUBROUTINE pair_potential_deepmd_create(deepmd)
      TYPE(deepmd_pot_type), POINTER                     :: deepmd

      CPASSERT(.NOT. ASSOCIATED(deepmd))
      ALLOCATE (deepmd)
   END SUBROUTINE pair_potential_deepmd_create

! **************************************************************************************************
!> \brief Copy two DEEPMD potential type
!> \param deepmd_source ...
!> \param deepmd_dest ...
!> \author Yongbin Zhuang 07.2019
! **************************************************************************************************
   SUBROUTINE pair_potential_deepmd_copy(deepmd_source, deepmd_dest)
      TYPE(deepmd_pot_type), POINTER                     :: deepmd_source, deepmd_dest

      IF (.NOT. ASSOCIATED(deepmd_source)) RETURN
      NULLIFY (deepmd_dest)
      IF (ASSOCIATED(deepmd_dest)) CALL pair_potential_deepmd_release(deepmd_dest)
      CALL pair_potential_deepmd_create(deepmd_dest)
      deepmd_dest = deepmd_source
   END SUBROUTINE pair_potential_deepmd_copy

! **************************************************************************************************
!> \brief CLEAN the DEEPMD potential type
!> \param deepmd ...
!> \author Yongbin Zhuang 07.2019
! **************************************************************************************************
   SUBROUTINE pair_potential_deepmd_clean(deepmd)
      TYPE(deepmd_pot_type), POINTER                     :: deepmd

      IF (.NOT. ASSOCIATED(deepmd)) RETURN
      deepmd = deepmd_pot_type()
   END SUBROUTINE pair_potential_deepmd_clean

! **************************************************************************************************
!> \brief Destroys the DEEPMD potential type
!> \param deepmd ...
!> \author Yongbin Zhuang 07.2019
! **************************************************************************************************
   SUBROUTINE pair_potential_deepmd_release(deepmd)
      TYPE(deepmd_pot_type), POINTER                     :: deepmd

      IF (ASSOCIATED(deepmd)) THEN
         DEALLOCATE (deepmd)
      END IF
   END SUBROUTINE pair_potential_deepmd_release

! **************************************************************************************************
!> \brief Creates the QUIP potential type
!> \param quip ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_quip_create(quip)
      TYPE(quip_pot_type), POINTER                       :: quip

      CPASSERT(.NOT. ASSOCIATED(quip))
      ALLOCATE (quip)
      quip%quip_file_name = ""
      quip%init_args = ""
      quip%calc_args = ""
      CALL pair_potential_quip_clean(quip)
   END SUBROUTINE pair_potential_quip_create

! **************************************************************************************************
!> \brief Copy two QUIP potential type
!> \param quip_source ...
!> \param quip_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_quip_copy(quip_source, quip_dest)
      TYPE(quip_pot_type), POINTER                       :: quip_source, quip_dest

      IF (.NOT. ASSOCIATED(quip_source)) RETURN
      IF (ASSOCIATED(quip_dest)) CALL pair_potential_quip_release(quip_dest)
      CALL pair_potential_quip_create(quip_dest)
      quip_dest%quip_file_name = quip_source%quip_file_name
      quip_dest%init_args = quip_source%init_args
      quip_dest%calc_args = quip_source%calc_args
   END SUBROUTINE pair_potential_quip_copy

! **************************************************************************************************
!> \brief Creates the QUIP potential type
!> \param quip ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_quip_clean(quip)
      TYPE(quip_pot_type), POINTER                       :: quip

      IF (.NOT. ASSOCIATED(quip)) RETURN
      quip%quip_file_name = 'NULL'
      quip%init_args = ''
      quip%calc_args = ''
   END SUBROUTINE pair_potential_quip_clean

! **************************************************************************************************
!> \brief Destroys the QUIP potential type
!> \param quip ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_quip_release(quip)
      TYPE(quip_pot_type), POINTER                       :: quip

      IF (ASSOCIATED(quip)) THEN
         DEALLOCATE (quip)
      END IF
   END SUBROUTINE pair_potential_quip_release

! **************************************************************************************************
!> \brief Creates the NEQUIP potential type
!> \param nequip ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_nequip_create(nequip)
      TYPE(nequip_pot_type), POINTER                     :: nequip

      CPASSERT(.NOT. ASSOCIATED(nequip))
      ALLOCATE (nequip)
   END SUBROUTINE pair_potential_nequip_create

! **************************************************************************************************
!> \brief Copy two NEQUIP potential type
!> \param nequip_source ...
!> \param nequip_dest ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_nequip_copy(nequip_source, nequip_dest)
      TYPE(nequip_pot_type), POINTER                     :: nequip_source, nequip_dest

      IF (.NOT. ASSOCIATED(nequip_source)) RETURN
      IF (ASSOCIATED(nequip_dest)) CALL pair_potential_nequip_release(nequip_dest)
      CALL pair_potential_nequip_create(nequip_dest)
      nequip_dest = nequip_source

   END SUBROUTINE pair_potential_nequip_copy

! **************************************************************************************************
!> \brief Creates the NEQUIP potential type
!> \param nequip ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_nequip_clean(nequip)
      TYPE(nequip_pot_type), POINTER                     :: nequip

      IF (.NOT. ASSOCIATED(nequip)) RETURN
      nequip = nequip_pot_type()

   END SUBROUTINE pair_potential_nequip_clean

! **************************************************************************************************
!> \brief Destroys the NEQUIP potential type
!> \param nequip ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_nequip_release(nequip)
      TYPE(nequip_pot_type), POINTER                     :: nequip

      IF (ASSOCIATED(nequip)) THEN
         DEALLOCATE (nequip)
      END IF
   END SUBROUTINE pair_potential_nequip_release

! **************************************************************************************************
!> \brief Creates the ALLEGRO potential type
!> \param allegro ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_allegro_create(allegro)
      TYPE(allegro_pot_type), POINTER                    :: allegro

      CPASSERT(.NOT. ASSOCIATED(allegro))
      ALLOCATE (allegro)
   END SUBROUTINE pair_potential_allegro_create

! **************************************************************************************************
!> \brief Copy two ALLEGRO potential type
!> \param allegro_source ...
!> \param allegro_dest ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_allegro_copy(allegro_source, allegro_dest)
      TYPE(allegro_pot_type), POINTER                    :: allegro_source, allegro_dest

      IF (.NOT. ASSOCIATED(allegro_source)) RETURN
      IF (ASSOCIATED(allegro_dest)) CALL pair_potential_allegro_release(allegro_dest)
      CALL pair_potential_allegro_create(allegro_dest)
      allegro_dest = allegro_source
   END SUBROUTINE pair_potential_allegro_copy

! **************************************************************************************************
!> \brief Creates the ALLEGRO potential type
!> \param allegro ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_allegro_clean(allegro)
      TYPE(allegro_pot_type), POINTER                    :: allegro

      IF (.NOT. ASSOCIATED(allegro)) RETURN
      allegro = allegro_pot_type()

   END SUBROUTINE pair_potential_allegro_clean

! **************************************************************************************************
!> \brief Destroys the ALLEGRO potential type
!> \param allegro ...
!> \author Gabriele Tocci 2023
! **************************************************************************************************
   SUBROUTINE pair_potential_allegro_release(allegro)
      TYPE(allegro_pot_type), POINTER                    :: allegro

      IF (ASSOCIATED(allegro)) THEN
         DEALLOCATE (allegro)
      END IF
   END SUBROUTINE pair_potential_allegro_release

! **************************************************************************************************
!> \brief Creates the BMHFT (TOSI-FUMI) potential type
!> \param ft ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhft_create(ft)
      TYPE(ft_pot_type), POINTER                         :: ft

      CPASSERT(.NOT. ASSOCIATED(ft))
      ALLOCATE (ft)
      CALL pair_potential_bmhft_clean(ft)
   END SUBROUTINE pair_potential_bmhft_create

! **************************************************************************************************
!> \brief Copy two BMHFT (TOSI-FUMI) potential type
!> \param ft_source ...
!> \param ft_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhft_copy(ft_source, ft_dest)
      TYPE(ft_pot_type), POINTER                         :: ft_source, ft_dest

      IF (.NOT. ASSOCIATED(ft_source)) RETURN
      IF (ASSOCIATED(ft_dest)) CALL pair_potential_bmhft_release(ft_dest)
      CALL pair_potential_bmhft_create(ft_dest)
      ft_dest%A = ft_source%A
      ft_dest%B = ft_source%B
      ft_dest%C = ft_source%C
      ft_dest%D = ft_source%D
   END SUBROUTINE pair_potential_bmhft_copy

! **************************************************************************************************
!> \brief Creates the BMHFT (TOSI-FUMI) potential type
!> \param ft ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhft_clean(ft)
      TYPE(ft_pot_type), POINTER                         :: ft

      IF (.NOT. ASSOCIATED(ft)) RETURN
      ft%A = 0.0_dp
      ft%B = 0.0_dp
      ft%C = 0.0_dp
      ft%D = 0.0_dp
   END SUBROUTINE pair_potential_bmhft_clean

! **************************************************************************************************
!> \brief Destroys the BMHFT potential type
!> \param ft ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhft_release(ft)
      TYPE(ft_pot_type), POINTER                         :: ft

      IF (ASSOCIATED(ft)) THEN
         DEALLOCATE (ft)
      END IF
      NULLIFY (ft)
   END SUBROUTINE pair_potential_bmhft_release

! **************************************************************************************************
!> \brief Creates the BMHFTD (damped TOSI-FUMI) potential type
!> \param ftd ...
!> \author Mathieu Salanne 05.2010
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhftd_create(ftd)
      TYPE(ftd_pot_type), POINTER                        :: ftd

      CPASSERT(.NOT. ASSOCIATED(ftd))
      ALLOCATE (ftd)
      CALL pair_potential_bmhftd_clean(ftd)
   END SUBROUTINE pair_potential_bmhftd_create

! **************************************************************************************************
!> \brief Copy two BMHFTD (Damped TOSI-FUMI) potential type
!> \param ftd_source ...
!> \param ftd_dest ...
!> \author Mathieu Salanne 05.2010
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhftd_copy(ftd_source, ftd_dest)
      TYPE(ftd_pot_type), POINTER                        :: ftd_source, ftd_dest

      IF (.NOT. ASSOCIATED(ftd_source)) RETURN
      IF (ASSOCIATED(ftd_dest)) CALL pair_potential_bmhftd_release(ftd_dest)
      CALL pair_potential_bmhftd_create(ftd_dest)
      ftd_dest%A = ftd_source%A
      ftd_dest%B = ftd_source%B
      ftd_dest%C = ftd_source%C
      ftd_dest%D = ftd_source%D
      ftd_dest%BD = ftd_source%BD
   END SUBROUTINE pair_potential_bmhftd_copy

! **************************************************************************************************
!> \brief Cleans the BMHFTD (damped TOSI-FUMI) potential type
!> \param ftd ...
!> \author Mathieu Salanne
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhftd_clean(ftd)
      TYPE(ftd_pot_type), POINTER                        :: ftd

      IF (.NOT. ASSOCIATED(ftd)) RETURN
      ftd%A = 0.0_dp
      ftd%B = 0.0_dp
      ftd%C = 0.0_dp
      ftd%D = 0.0_dp
      ftd%BD = 0.0_dp
   END SUBROUTINE pair_potential_bmhftd_clean

! **************************************************************************************************
!> \brief Destroys the BMHFTD potential type
!> \param ftd ...
!> \author Mathieu Salanne 05.2010
! **************************************************************************************************
   SUBROUTINE pair_potential_bmhftd_release(ftd)
      TYPE(ftd_pot_type), POINTER                        :: ftd

      IF (ASSOCIATED(ftd)) THEN
         DEALLOCATE (ftd)
      END IF
      NULLIFY (ftd)
   END SUBROUTINE pair_potential_bmhftd_release

! **************************************************************************************************
!> \brief Creates the IPBV potential type
!> \param ipbv ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_ipbv_create(ipbv)
      TYPE(ipbv_pot_type), POINTER                       :: ipbv

      CPASSERT(.NOT. ASSOCIATED(ipbv))
      ALLOCATE (ipbv)
      CALL pair_potential_ipbv_clean(ipbv)
   END SUBROUTINE pair_potential_ipbv_create

! **************************************************************************************************
!> \brief Copy two IPBV potential type
!> \param ipbv_source ...
!> \param ipbv_dest ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_ipbv_copy(ipbv_source, ipbv_dest)
      TYPE(ipbv_pot_type), POINTER                       :: ipbv_source, ipbv_dest

      IF (.NOT. ASSOCIATED(ipbv_source)) RETURN
      IF (ASSOCIATED(ipbv_dest)) CALL pair_potential_ipbv_release(ipbv_dest)
      CALL pair_potential_ipbv_create(ipbv_dest)
      ipbv_dest%a = ipbv_source%a
      ipbv_dest%rcore = ipbv_source%rcore
      ipbv_dest%b = ipbv_source%b
      ipbv_dest%m = ipbv_source%m
   END SUBROUTINE pair_potential_ipbv_copy

! **************************************************************************************************
!> \brief Creates the IPBV potential type
!> \param ipbv ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_ipbv_clean(ipbv)
      TYPE(ipbv_pot_type), POINTER                       :: ipbv

      IF (.NOT. ASSOCIATED(ipbv)) RETURN
      ipbv%a = 0.0_dp
      ipbv%rcore = 0.0_dp
      ipbv%b = 0.0_dp
      ipbv%m = 0.0_dp
   END SUBROUTINE pair_potential_ipbv_clean

! **************************************************************************************************
!> \brief Destroys the IPBV potential type
!> \param ipbv ...
!> \author Teodoro Laino [teo] 11.2005
! **************************************************************************************************
   SUBROUTINE pair_potential_ipbv_release(ipbv)
      TYPE(ipbv_pot_type), POINTER                       :: ipbv

      IF (ASSOCIATED(ipbv)) THEN
         DEALLOCATE (ipbv)
      END IF
      NULLIFY (ipbv)
   END SUBROUTINE pair_potential_ipbv_release

! **************************************************************************************************
!> \brief Creates the Buckingham 4 ranges  potential type
!> \param buck4r ...
!> \author MI 10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buck4r_create(buck4r)
      TYPE(buck4ran_pot_type), POINTER                   :: buck4r

      CPASSERT(.NOT. ASSOCIATED(buck4r))
      ALLOCATE (buck4r)
      CALL pair_potential_buck4r_clean(buck4r)
   END SUBROUTINE pair_potential_buck4r_create

! **************************************************************************************************
!> \brief Copy two Buckingham 4 ranges  potential type
!> \param buck4r_source ...
!> \param buck4r_dest ...
!> \author MI 10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buck4r_copy(buck4r_source, buck4r_dest)
      TYPE(buck4ran_pot_type), POINTER                   :: buck4r_source, buck4r_dest

      IF (.NOT. ASSOCIATED(buck4r_source)) RETURN
      IF (ASSOCIATED(buck4r_dest)) CALL pair_potential_buck4r_release(buck4r_dest)
      CALL pair_potential_buck4r_create(buck4r_dest)
      buck4r_dest%a = buck4r_source%a
      buck4r_dest%b = buck4r_source%b
      buck4r_dest%c = buck4r_source%c
      buck4r_dest%r1 = buck4r_source%r1
      buck4r_dest%r2 = buck4r_source%r2
      buck4r_dest%r3 = buck4r_source%r3
      buck4r_dest%poly1 = buck4r_source%poly1
      buck4r_dest%poly2 = buck4r_source%poly2
      buck4r_dest%npoly1 = buck4r_source%npoly1
      buck4r_dest%npoly2 = buck4r_source%npoly2
   END SUBROUTINE pair_potential_buck4r_copy

! **************************************************************************************************
!> \brief Creates the Buckingham 4 ranges  potential type
!> \param buck4r ...
!> \author MI 10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buck4r_clean(buck4r)
      TYPE(buck4ran_pot_type), POINTER                   :: buck4r

      IF (.NOT. ASSOCIATED(buck4r)) RETURN
      buck4r%a = 0.0_dp
      buck4r%b = 0.0_dp
      buck4r%c = 0.0_dp
      buck4r%r1 = 0.0_dp
      buck4r%r2 = 0.0_dp
      buck4r%r3 = 0.0_dp
      buck4r%poly1 = 0.0_dp
      buck4r%npoly1 = 0
      buck4r%poly2 = 0.0_dp
      buck4r%npoly2 = 0
   END SUBROUTINE pair_potential_buck4r_clean

! **************************************************************************************************
!> \brief Destroys the Buckingham 4 ranges potential type
!> \param buck4r ...
!> \author MI  10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buck4r_release(buck4r)
      TYPE(buck4ran_pot_type), POINTER                   :: buck4r

      IF (ASSOCIATED(buck4r)) THEN
         DEALLOCATE (buck4r)
      END IF
      NULLIFY (buck4r)
   END SUBROUTINE pair_potential_buck4r_release

! **************************************************************************************************
!> \brief Creates the Buckingham plus Morse potential type
!> \param buckmo ...
!> \author MI 10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buckmo_create(buckmo)
      TYPE(buckmorse_pot_type), POINTER                  :: buckmo

      CPASSERT(.NOT. ASSOCIATED(buckmo))
      ALLOCATE (buckmo)
      CALL pair_potential_buckmo_clean(buckmo)
   END SUBROUTINE pair_potential_buckmo_create

! **************************************************************************************************
!> \brief Copy two Buckingham plus Morse  potential type
!> \param buckmo_source ...
!> \param buckmo_dest ...
!> \author MI 10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buckmo_copy(buckmo_source, buckmo_dest)
      TYPE(buckmorse_pot_type), POINTER                  :: buckmo_source, buckmo_dest

      IF (.NOT. ASSOCIATED(buckmo_source)) RETURN
      IF (ASSOCIATED(buckmo_dest)) CALL pair_potential_buckmo_release(buckmo_dest)
      CALL pair_potential_buckmo_create(buckmo_dest)
      buckmo_dest%f0 = buckmo_source%f0
      buckmo_dest%a1 = buckmo_source%a1
      buckmo_dest%a2 = buckmo_source%a2
      buckmo_dest%b1 = buckmo_source%b1
      buckmo_dest%b2 = buckmo_source%b2
      buckmo_dest%c = buckmo_source%c
      buckmo_dest%d = buckmo_source%d
      buckmo_dest%r0 = buckmo_source%r0
      buckmo_dest%beta = buckmo_source%beta
   END SUBROUTINE pair_potential_buckmo_copy

! **************************************************************************************************
!> \brief Creates the Buckingham plus Morse  potential type
!> \param buckmo ...
!> \author MI 10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buckmo_clean(buckmo)
      TYPE(buckmorse_pot_type), POINTER                  :: buckmo

      IF (.NOT. ASSOCIATED(buckmo)) RETURN
      buckmo%f0 = 0.0_dp
      buckmo%a1 = 0.0_dp
      buckmo%a2 = 0.0_dp
      buckmo%b1 = 0.0_dp
      buckmo%b2 = 0.0_dp
      buckmo%c = 0.0_dp
      buckmo%d = 0.0_dp
      buckmo%r0 = 0.0_dp
      buckmo%beta = 0.0_dp
   END SUBROUTINE pair_potential_buckmo_clean

! **************************************************************************************************
!> \brief Destroys the Buckingham plus Morse potential type
!> \param buckmo ...
!> \author MI  10.2006
! **************************************************************************************************
   SUBROUTINE pair_potential_buckmo_release(buckmo)
      TYPE(buckmorse_pot_type), POINTER                  :: buckmo

      IF (ASSOCIATED(buckmo)) THEN
         DEALLOCATE (buckmo)
      END IF
      NULLIFY (buckmo)
   END SUBROUTINE pair_potential_buckmo_release

! **************************************************************************************************
!> \brief Creates the Tersoff potential type
!>      (Tersoff, J. PRB 39(8), 5566, 1989)
!> \param tersoff ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tersoff_create(tersoff)
      TYPE(tersoff_pot_type), POINTER                    :: tersoff

      CPASSERT(.NOT. ASSOCIATED(tersoff))
      ALLOCATE (tersoff)
      CALL pair_potential_tersoff_clean(tersoff)
   END SUBROUTINE pair_potential_tersoff_create

! **************************************************************************************************
!> \brief Copy two Tersoff potential type
!>      (Tersoff, J. PRB 39(8), 5566, 1989)
!> \param tersoff_source ...
!> \param tersoff_dest ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tersoff_copy(tersoff_source, tersoff_dest)
      TYPE(tersoff_pot_type), POINTER                    :: tersoff_source, tersoff_dest

      IF (.NOT. ASSOCIATED(tersoff_source)) RETURN
      IF (ASSOCIATED(tersoff_dest)) CALL pair_potential_tersoff_release(tersoff_dest)
      CALL pair_potential_tersoff_create(tersoff_dest)
      tersoff_dest%A = tersoff_source%A
      tersoff_dest%B = tersoff_source%B
      tersoff_dest%lambda1 = tersoff_source%lambda1
      tersoff_dest%lambda2 = tersoff_source%lambda2
      tersoff_dest%alpha = tersoff_source%alpha
      tersoff_dest%beta = tersoff_source%beta
      tersoff_dest%n = tersoff_source%n
      tersoff_dest%c = tersoff_source%c
      tersoff_dest%d = tersoff_source%d
      tersoff_dest%h = tersoff_source%h
      tersoff_dest%lambda3 = tersoff_source%lambda3
      tersoff_dest%bigR = tersoff_source%bigR
      tersoff_dest%bigD = tersoff_source%bigD
      tersoff_dest%rcutsq = tersoff_source%rcutsq
   END SUBROUTINE pair_potential_tersoff_copy

! **************************************************************************************************
!> \brief Creates the Tersoff potential type
!>      (Tersoff, J. PRB 39(8), 5566, 1989)
!> \param tersoff ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tersoff_clean(tersoff)
      TYPE(tersoff_pot_type), POINTER                    :: tersoff

      IF (.NOT. ASSOCIATED(tersoff)) RETURN
      tersoff%A = 0.0_dp
      tersoff%B = 0.0_dp
      tersoff%lambda1 = 0.0_dp
      tersoff%lambda2 = 0.0_dp
      tersoff%alpha = 0.0_dp
      tersoff%beta = 0.0_dp
      tersoff%n = 0.0_dp
      tersoff%c = 0.0_dp
      tersoff%d = 0.0_dp
      tersoff%h = 0.0_dp
      tersoff%lambda3 = 0.0_dp
      tersoff%bigR = 0.0_dp
      tersoff%bigD = 0.0_dp
      tersoff%rcutsq = 0.0_dp
   END SUBROUTINE pair_potential_tersoff_clean

! **************************************************************************************************
!> \brief Destroys the Tersoff
!>      (Tersoff, J. PRB 39(8), 5566, 1989)
!> \param tersoff ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tersoff_release(tersoff)
      TYPE(tersoff_pot_type), POINTER                    :: tersoff

      IF (ASSOCIATED(tersoff)) THEN
         DEALLOCATE (tersoff)
      END IF
      NULLIFY (tersoff)
   END SUBROUTINE pair_potential_tersoff_release

! **************************************************************************************************
!> \brief Creates the Siepmann-Sprik potential type
!>      (Siepmann and Sprik, J. Chem. Phys. 102(1) 511, 1995)
!> \param siepmann ...
! **************************************************************************************************
   SUBROUTINE pair_potential_siepmann_create(siepmann)
      TYPE(siepmann_pot_type), POINTER                   :: siepmann

      CPASSERT(.NOT. ASSOCIATED(siepmann))
      ALLOCATE (siepmann)
      CALL pair_potential_siepmann_clean(siepmann)
   END SUBROUTINE pair_potential_siepmann_create
! **************************************************************************************************
!> \brief Copy two Siepmann potential type
!>      (Siepmann and Sprik, J. Chem. Phys. 102(1) 511, 1995)
!> \param siepmann_source ...
!> \param siepmann_dest ...
! **************************************************************************************************
   SUBROUTINE pair_potential_siepmann_copy(siepmann_source, siepmann_dest)
      TYPE(siepmann_pot_type), POINTER                   :: siepmann_source, siepmann_dest

      IF (.NOT. ASSOCIATED(siepmann_source)) RETURN
      IF (ASSOCIATED(siepmann_dest)) CALL pair_potential_siepmann_release(siepmann_dest)
      CALL pair_potential_siepmann_create(siepmann_dest)
      siepmann_dest%B = siepmann_source%B
      siepmann_dest%D = siepmann_source%D
      siepmann_dest%E = siepmann_source%E
      siepmann_dest%F = siepmann_source%F
      siepmann_dest%beta = siepmann_source%beta
      siepmann_dest%rcutsq = siepmann_source%rcutsq
      siepmann_dest%allow_oh_formation = siepmann_source%allow_oh_formation
      siepmann_dest%allow_h3o_formation = siepmann_source%allow_h3o_formation
      siepmann_dest%allow_o_formation = siepmann_source%allow_o_formation

   END SUBROUTINE pair_potential_siepmann_copy

! **************************************************************************************************
!> \brief Creates the Siepmann-Sprik potential type
!>      (Siepmann and Sprik, J. Chem. Phys. 102(1) 511, 1995)
!> \param siepmann ...
! **************************************************************************************************
   SUBROUTINE pair_potential_siepmann_clean(siepmann)
      TYPE(siepmann_pot_type), POINTER                   :: siepmann

      IF (.NOT. ASSOCIATED(siepmann)) RETURN
      siepmann%B = 0.0_dp
      siepmann%D = 0.0_dp
      siepmann%E = 0.0_dp
      siepmann%F = 0.0_dp
      siepmann%beta = 0.0_dp
      siepmann%rcutsq = 0.0_dp
      siepmann%allow_oh_formation = .FALSE.
      siepmann%allow_h3o_formation = .FALSE.
      siepmann%allow_o_formation = .FALSE.

   END SUBROUTINE pair_potential_siepmann_clean

! **************************************************************************************************
!> \brief Destroys the Siepmann-Sprik potential
!>      (Siepmann and Sprik, J. Chem. Phys. 102(1) 511, 1995)
!> \param siepmann ...
! **************************************************************************************************
   SUBROUTINE pair_potential_siepmann_release(siepmann)
      TYPE(siepmann_pot_type), POINTER                   :: siepmann

      IF (ASSOCIATED(siepmann)) THEN
         DEALLOCATE (siepmann)
      END IF
      NULLIFY (siepmann)
   END SUBROUTINE pair_potential_siepmann_release

! **************************************************************************************************
!> \brief Creates the GAL19 potential type
!>      (??)
!> \param gal ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal_create(gal)
      TYPE(gal_pot_type), POINTER                        :: gal

      CPASSERT(.NOT. ASSOCIATED(gal))
      ALLOCATE (gal)
      CALL pair_potential_gal_clean(gal)
   END SUBROUTINE pair_potential_gal_create

! **************************************************************************************************
!> \brief Copy two GAL potential type
!>      (??)
!> \param gal_source ...
!> \param gal_dest ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal_copy(gal_source, gal_dest)
      TYPE(gal_pot_type), POINTER                        :: gal_source, gal_dest

      IF (.NOT. ASSOCIATED(gal_source)) RETURN
      IF (ASSOCIATED(gal_dest)) CALL pair_potential_gal_release(gal_dest)
      CALL pair_potential_gal_create(gal_dest)
      gal_dest%met1 = gal_source%met1
      gal_dest%met2 = gal_source%met2
      gal_dest%epsilon = gal_source%epsilon
      gal_dest%bxy = gal_source%bxy
      gal_dest%bz = gal_source%bz
      gal_dest%r1 = gal_source%r1
      gal_dest%r2 = gal_source%r2
      gal_dest%a1 = gal_source%a1
      gal_dest%a2 = gal_source%a2
      gal_dest%a3 = gal_source%a3
      gal_dest%a4 = gal_source%a4
      gal_dest%a = gal_source%a
      gal_dest%b = gal_source%b
      gal_dest%c = gal_source%c
      ALLOCATE (gal_dest%gcn(SIZE(gal_source%gcn)))
      gal_dest%gcn = gal_source%gcn
      gal_dest%express = gal_source%express
      gal_dest%rcutsq = gal_source%rcutsq

   END SUBROUTINE pair_potential_gal_copy

! **************************************************************************************************
!> \brief Creates the GAL19 potential type
!>      (??)
!> \param gal ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal_clean(gal)
      TYPE(gal_pot_type), POINTER                        :: gal

      IF (.NOT. ASSOCIATED(gal)) RETURN
      gal%epsilon = 0.0_dp
      gal%bxy = 0.0_dp
      gal%bz = 0.0_dp
      gal%r1 = 0.0_dp
      gal%r2 = 0.0_dp
      gal%a1 = 0.0_dp
      gal%a2 = 0.0_dp
      gal%a3 = 0.0_dp
      gal%a4 = 0.0_dp
      gal%a = 0.0_dp
      gal%b = 0.0_dp
      gal%c = 0.0_dp
      gal%rcutsq = 0.0_dp
      gal%express = .FALSE.

   END SUBROUTINE pair_potential_gal_clean

! **************************************************************************************************
!> \brief Destroys the GAL19 potential
!>      (??)
!> \param gal ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal_release(gal)
      TYPE(gal_pot_type), POINTER                        :: gal

      IF (ASSOCIATED(gal)) THEN
         DEALLOCATE (gal%gcn)
         DEALLOCATE (gal)
      END IF
      NULLIFY (gal)
   END SUBROUTINE pair_potential_gal_release

! **************************************************************************************************
!> \brief Creates the GAL21 potential type
!>      (??)
!> \param gal21 ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal21_create(gal21)
      TYPE(gal21_pot_type), POINTER                      :: gal21

      CPASSERT(.NOT. ASSOCIATED(gal21))
      ALLOCATE (gal21)
      CALL pair_potential_gal21_clean(gal21)
   END SUBROUTINE pair_potential_gal21_create

! **************************************************************************************************
!> \brief Copy two GAL21 potential type
!>      (??)
!> \param gal21_source ...
!> \param gal21_dest ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal21_copy(gal21_source, gal21_dest)
      TYPE(gal21_pot_type), POINTER                      :: gal21_source, gal21_dest

      IF (.NOT. ASSOCIATED(gal21_source)) RETURN
      IF (ASSOCIATED(gal21_dest)) CALL pair_potential_gal21_release(gal21_dest)
      CALL pair_potential_gal21_create(gal21_dest)
      gal21_dest%met1 = gal21_source%met1
      gal21_dest%met2 = gal21_source%met2
      gal21_dest%epsilon1 = gal21_source%epsilon1
      gal21_dest%epsilon2 = gal21_source%epsilon2
      gal21_dest%epsilon3 = gal21_source%epsilon3
      gal21_dest%bxy1 = gal21_source%bxy1
      gal21_dest%bxy2 = gal21_source%bxy2
      gal21_dest%bz1 = gal21_source%bz1
      gal21_dest%bz2 = gal21_source%bz2
      gal21_dest%r1 = gal21_source%r1
      gal21_dest%r2 = gal21_source%r2
      gal21_dest%a11 = gal21_source%a11
      gal21_dest%a12 = gal21_source%a12
      gal21_dest%a13 = gal21_source%a13
      gal21_dest%a21 = gal21_source%a21
      gal21_dest%a22 = gal21_source%a22
      gal21_dest%a23 = gal21_source%a23
      gal21_dest%a31 = gal21_source%a31
      gal21_dest%a32 = gal21_source%a32
      gal21_dest%a33 = gal21_source%a33
      gal21_dest%a41 = gal21_source%a41
      gal21_dest%a42 = gal21_source%a42
      gal21_dest%a43 = gal21_source%a43
      gal21_dest%AO1 = gal21_source%AO1
      gal21_dest%AO2 = gal21_source%AO2
      gal21_dest%BO1 = gal21_source%BO1
      gal21_dest%BO2 = gal21_source%BO2
      gal21_dest%c = gal21_source%c
      gal21_dest%AH1 = gal21_source%AH1
      gal21_dest%AH2 = gal21_source%AH2
      gal21_dest%BH1 = gal21_source%BH1
      gal21_dest%BH2 = gal21_source%BH2
      ALLOCATE (gal21_dest%gcn(SIZE(gal21_source%gcn)))
      gal21_dest%gcn = gal21_source%gcn
      gal21_dest%express = gal21_source%express
      gal21_dest%rcutsq = gal21_source%rcutsq

   END SUBROUTINE pair_potential_gal21_copy

! **************************************************************************************************
!> \brief Creates the GAL21 potential type
!>      (??)
!> \param gal21 ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal21_clean(gal21)
      TYPE(gal21_pot_type), POINTER                      :: gal21

      IF (.NOT. ASSOCIATED(gal21)) RETURN
      gal21%epsilon1 = 0.0_dp
      gal21%epsilon2 = 0.0_dp
      gal21%epsilon3 = 0.0_dp
      gal21%bxy1 = 0.0_dp
      gal21%bxy2 = 0.0_dp
      gal21%bz1 = 0.0_dp
      gal21%bz2 = 0.0_dp
      gal21%r1 = 0.0_dp
      gal21%r2 = 0.0_dp
      gal21%a11 = 0.0_dp
      gal21%a12 = 0.0_dp
      gal21%a13 = 0.0_dp
      gal21%a21 = 0.0_dp
      gal21%a22 = 0.0_dp
      gal21%a23 = 0.0_dp
      gal21%a31 = 0.0_dp
      gal21%a32 = 0.0_dp
      gal21%a33 = 0.0_dp
      gal21%a41 = 0.0_dp
      gal21%a42 = 0.0_dp
      gal21%a43 = 0.0_dp
      gal21%AO1 = 0.0_dp
      gal21%AO2 = 0.0_dp
      gal21%BO1 = 0.0_dp
      gal21%BO2 = 0.0_dp
      gal21%c = 0.0_dp
      gal21%AH1 = 0.0_dp
      gal21%AH2 = 0.0_dp
      gal21%BH1 = 0.0_dp
      gal21%BH2 = 0.0_dp
      gal21%rcutsq = 0.0_dp
      gal21%express = .FALSE.

   END SUBROUTINE pair_potential_gal21_clean

! **************************************************************************************************
!> \brief Destroys the GAL21 potential
!>      (??)
!> \param gal21 ...
! **************************************************************************************************
   SUBROUTINE pair_potential_gal21_release(gal21)
      TYPE(gal21_pot_type), POINTER                      :: gal21

      IF (ASSOCIATED(gal21)) THEN
         DEALLOCATE (gal21%gcn)
         DEALLOCATE (gal21)
      END IF
      NULLIFY (gal21)
   END SUBROUTINE pair_potential_gal21_release

! **************************************************************************************************
!> \brief Creates the TABPOT potential type
!> \param tab ...
!> \author Alex Mironenko, Da Teng 2019-2022
! **************************************************************************************************
   SUBROUTINE pair_potential_tab_create(tab)
      TYPE(tab_pot_type), POINTER                        :: tab

      CPASSERT(.NOT. ASSOCIATED(tab))
      ALLOCATE (tab)
      NULLIFY (tab%r, tab%e, tab%f)
      CALL pair_potential_tab_clean(tab)
   END SUBROUTINE pair_potential_tab_create

! **************************************************************************************************
!> \brief Copy two TABPOT potential type
!> \param tab_source ...
!> \param tab_dest ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tab_copy(tab_source, tab_dest)
      TYPE(tab_pot_type), POINTER                        :: tab_source, tab_dest

      IF (.NOT. ASSOCIATED(tab_source)) RETURN
      IF (ASSOCIATED(tab_dest)) CALL pair_potential_tab_release(tab_dest)
      CALL pair_potential_tab_create(tab_dest)
      tab_dest%tabpot_file_name = tab_source%tabpot_file_name
      tab_dest%dr = tab_source%dr
      tab_dest%rcut = tab_source%rcut
      tab_dest%npoints = tab_source%npoints
      tab_dest%index = tab_source%index
      ! Allocate arrays with the proper size
      CALL reallocate(tab_dest%r, 1, tab_dest%npoints)
      CALL reallocate(tab_dest%e, 1, tab_dest%npoints)
      CALL reallocate(tab_dest%f, 1, tab_dest%npoints)
      tab_dest%r = tab_source%r
      tab_dest%e = tab_source%e
      tab_dest%f = tab_source%f
   END SUBROUTINE pair_potential_tab_copy

! **************************************************************************************************
!> \brief Creates the TABPOT potential type
!> \param tab ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tab_clean(tab)
      TYPE(tab_pot_type), POINTER                        :: tab

      IF (.NOT. ASSOCIATED(tab)) RETURN
      tab%tabpot_file_name = 'NULL'
      tab%dr = 0.0_dp
      tab%rcut = 0.0_dp
      tab%npoints = 0
      tab%index = 0
      CALL reallocate(tab%r, 1, tab%npoints)
      CALL reallocate(tab%e, 1, tab%npoints)
      CALL reallocate(tab%f, 1, tab%npoints)

   END SUBROUTINE pair_potential_tab_clean

! **************************************************************************************************
!> \brief Destroys the TABPOT potential type
!> \param tab ...
! **************************************************************************************************
   SUBROUTINE pair_potential_tab_release(tab)
      TYPE(tab_pot_type), POINTER                        :: tab

      IF (ASSOCIATED(tab)) THEN
         IF (ASSOCIATED(tab%r)) THEN
            DEALLOCATE (tab%r)
         END IF
         IF (ASSOCIATED(tab%e)) THEN
            DEALLOCATE (tab%e)
         END IF
         IF (ASSOCIATED(tab%f)) THEN
            DEALLOCATE (tab%f)
         END IF
         DEALLOCATE (tab)
      END IF
   END SUBROUTINE pair_potential_tab_release

END MODULE pair_potential_types

